aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2015-07-01 08:37:19 +0000
committerRichard Biener <rguenther@suse.de>2015-07-01 08:37:19 +0000
commitd9ab4649161bc60fc68c9bb36d54b28142a3797a (patch)
treee4a5056a7da5f93f5dbacd47b6f22b61fdf92aad
parente79886b1b133e4fd15f1c5c16d3e5a28c1233c33 (diff)
parent00b24710e5527e8b51904824c6e2a7717455c233 (diff)
2015-07-01 Richard Biener <rguenther@suse.de>match-and-simplify
Merge from trunk r225116 through r225225. * match-bitwise.pd: Removed and merged remains into match.pd. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/match-and-simplify@225229 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog6
-rw-r--r--config/ChangeLog5
-rw-r--r--config/dfp.m42
-rwxr-xr-xconfigure2
-rw-r--r--configure.ac2
-rw-r--r--gcc/ChangeLog330
-rw-r--r--gcc/ChangeLog.mas5
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog12
-rw-r--r--gcc/ada/gcc-interface/misc.c3
-rw-r--r--gcc/ada/gcc-interface/utils.c16
-rw-r--r--gcc/alias.c20
-rw-r--r--gcc/bb-reorder.c8
-rw-r--r--gcc/c-family/ChangeLog29
-rw-r--r--gcc/c-family/c-ada-spec.c1
-rw-r--r--gcc/c-family/c-common.c103
-rw-r--r--gcc/c-family/c-common.h7
-rw-r--r--gcc/c-family/c-lex.c4
-rw-r--r--gcc/c/ChangeLog14
-rw-r--r--gcc/c/c-decl.c4
-rw-r--r--gcc/c/c-typeck.c22
-rw-r--r--gcc/calls.c9
-rw-r--r--gcc/cfgrtl.c7
-rw-r--r--gcc/cgraphunit.c4
-rw-r--r--gcc/common/config/i386/i386-common.c16
-rw-r--r--gcc/config.gcc3
-rw-r--r--gcc/config/aarch64/aarch64-protos.h4
-rw-r--r--gcc/config/aarch64/aarch64.c14
-rw-r--r--gcc/config/aarch64/aarch64.md15
-rw-r--r--gcc/config/arm/arm.c20
-rw-r--r--gcc/config/c6x/c6x.c9
-rw-r--r--gcc/config/gnu-user.h9
-rw-r--r--gcc/config/i386/constraints.md5
-rw-r--r--gcc/config/i386/i386-c.c7
-rw-r--r--gcc/config/i386/i386.c242
-rw-r--r--gcc/config/i386/i386.h5
-rw-r--r--gcc/config/i386/i386.md104
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/iamcu.h42
-rw-r--r--gcc/config/nios2/nios2.c2
-rw-r--r--gcc/config/nvptx/nvptx.c46
-rw-r--r--gcc/config/sh/sh.md6
-rw-r--r--gcc/config/sparc/leon.md8
-rwxr-xr-xgcc/configure6
-rw-r--r--gcc/configure.ac4
-rw-r--r--gcc/cp/ChangeLog61
-rw-r--r--gcc/cp/call.c5
-rw-r--r--gcc/cp/cp-gimplify.c8
-rw-r--r--gcc/cp/cp-tree.h23
-rw-r--r--gcc/cp/decl.c76
-rw-r--r--gcc/cp/decl2.c8
-rw-r--r--gcc/cp/lex.c3
-rw-r--r--gcc/cp/parser.c3
-rw-r--r--gcc/cp/pt.c19
-rw-r--r--gcc/cp/semantics.c18
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/cse.c3
-rw-r--r--gcc/defaults.h60
-rw-r--r--gcc/df-scan.c15
-rw-r--r--gcc/doc/extend.texi78
-rw-r--r--gcc/doc/invoke.texi87
-rw-r--r--gcc/dojump.c9
-rw-r--r--gcc/dwarf2cfi.c5
-rw-r--r--gcc/expmed.c14
-rw-r--r--gcc/expr.c38
-rw-r--r--gcc/final.c12
-rw-r--r--gcc/fold-const.c253
-rw-r--r--gcc/function.c38
-rw-r--r--gcc/function.h1
-rw-r--r--gcc/genmatch.c13
-rw-r--r--gcc/haifa-sched.c5
-rw-r--r--gcc/ifcvt.c7
-rw-r--r--gcc/jit/ChangeLog180
-rw-r--r--gcc/jit/docs/_build/texinfo/libgccjit.texi1493
-rw-r--r--gcc/jit/docs/cp/topics/contexts.rst36
-rw-r--r--gcc/jit/docs/cp/topics/expressions.rst2
-rw-r--r--gcc/jit/docs/cp/topics/functions.rst84
-rw-r--r--gcc/jit/docs/cp/topics/objects.rst1
-rw-r--r--gcc/jit/docs/topics/compatibility.rst109
-rw-r--r--gcc/jit/docs/topics/contexts.rst65
-rw-r--r--gcc/jit/docs/topics/functions.rst96
-rw-r--r--gcc/jit/docs/topics/index.rst1
-rw-r--r--gcc/jit/docs/topics/objects.rst1
-rw-r--r--gcc/jit/jit-common.h12
-rw-r--r--gcc/jit/jit-playback.c78
-rw-r--r--gcc/jit/jit-playback.h21
-rw-r--r--gcc/jit/jit-recording.c424
-rw-r--r--gcc/jit/jit-recording.h106
-rw-r--r--gcc/jit/libgccjit++.h79
-rw-r--r--gcc/jit/libgccjit.c417
-rw-r--r--gcc/jit/libgccjit.h133
-rw-r--r--gcc/jit/libgccjit.map25
-rw-r--r--gcc/lra-constraints.c17
-rw-r--r--gcc/lra-int.h4
-rw-r--r--gcc/lra-lives.c2
-rw-r--r--gcc/lra.c41
-rw-r--r--gcc/lto-streamer-out.c34
-rw-r--r--gcc/match-bitwise.pd83
-rw-r--r--gcc/match.pd173
-rw-r--r--gcc/omp-low.c99
-rw-r--r--gcc/optabs.c20
-rw-r--r--gcc/po/ChangeLog4
-rw-r--r--gcc/po/sv.po1097
-rw-r--r--gcc/reorg.c2
-rw-r--r--gcc/stmt.c2
-rw-r--r--gcc/target-insns.def10
-rw-r--r--gcc/testsuite/ChangeLog133
-rw-r--r--gcc/testsuite/c-c++-common/pr60439.c96
-rw-r--r--gcc/testsuite/c-c++-common/pr66322.c144
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-friend-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-friend-3.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/udlit-utf8char.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/utf8-neg.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/utf8.C15
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/tls1.C7
-rw-r--r--gcc/testsuite/g++.dg/eh/scope1.C2
-rw-r--r--gcc/testsuite/g++.dg/template/pr66686.C15
-rw-r--r--gcc/testsuite/g++.dg/tls/tls_model1.C8
-rw-r--r--gcc/testsuite/gcc.dg/fold-ior-2.c47
-rw-r--r--gcc/testsuite/gcc.dg/fold-ior-3.c35
-rw-r--r--gcc/testsuite/gcc.dg/fold-minus-6.c42
-rw-r--r--gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-5.c22
-rw-r--r--gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-6.c22
-rw-r--r--gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-7.c22
-rw-r--r--gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-pr66652.c31
-rw-r--r--gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt.c21
-rw-r--r--gcc/testsuite/gcc.target/arm/armv8-sync-comp-swap.c10
-rw-r--r--gcc/testsuite/gcc.target/arm/armv8-sync-op-acquire.c10
-rw-r--r--gcc/testsuite/gcc.target/arm/armv8-sync-op-full.c10
-rw-r--r--gcc/testsuite/gcc.target/arm/armv8-sync-op-release.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/asm-flag-0.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/asm-flag-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/asm-flag-2.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/asm-flag-3.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/asm-flag-4.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/asm-flag-5.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp42
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/args.h77
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/asm-support.S302
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/defines.h110
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/macros.h53
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c521
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c57
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c162
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c83
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c608
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c182
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c237
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c97
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c221
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c362
-rw-r--r--gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c101
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66691.c64
-rw-r--r--gcc/testsuite/gfortran.dg/wunused-parameter.f9015
-rw-r--r--gcc/testsuite/gnat.dg/lto17.adb12
-rw-r--r--gcc/testsuite/gnat.dg/lto17.ads20
-rw-r--r--gcc/testsuite/jit.dg/all-non-failing-tests.h17
-rw-r--r--gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-NULL-case.c66
-rw-r--r--gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-mismatching-case-type.c83
-rw-r--r--gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-overlapping-ranges.c95
-rw-r--r--gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-non-const-label.c80
-rw-r--r--gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-non-integer-type.c81
-rw-r--r--gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-reversed-endpoints.c80
-rw-r--r--gcc/testsuite/jit.dg/test-extra-options.c136
-rw-r--r--gcc/testsuite/jit.dg/test-switch.c147
-rw-r--r--gcc/testsuite/jit.dg/test-switch.cc118
-rw-r--r--gcc/testsuite/jit.dg/test-validly-unreachable-block.c51
-rw-r--r--gcc/toplev.c6
-rw-r--r--gcc/tree-parloops.c78
-rw-r--r--gcc/tree-ssa-loop-ivopts.c4
-rw-r--r--gcc/tree-vect-data-refs.c5
-rw-r--r--gcc/tree-vrp.c38
-rw-r--r--gcc/typed-splay-tree.h135
-rw-r--r--libcpp/ChangeLog21
-rw-r--r--libcpp/charset.c8
-rw-r--r--libcpp/expr.c9
-rw-r--r--libcpp/include/cpplib.h5
-rw-r--r--libcpp/init.c36
-rw-r--r--libcpp/lex.c34
-rw-r--r--libcpp/macro.c2
-rw-r--r--libdecnumber/ChangeLog4
-rwxr-xr-xlibdecnumber/configure2
-rw-r--r--libgcc/ChangeLog7
-rw-r--r--libgcc/config.host3
-rw-r--r--libgcc/config/i386/32/t-iamcu1
-rw-r--r--libgcc/config/t-softfp-sfdftf5
-rw-r--r--libgcc/configure2
-rw-r--r--libgomp/ChangeLog64
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-1.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-16.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/c++.exp7
-rw-r--r--libgomp/testsuite/libgomp.c++/for-7.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/pr64824.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/pr64868.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/pr66199-1.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/pr66199-2.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/pr66702-1.C49
-rw-r--r--libgomp/testsuite/libgomp.c++/pr66702-2.C34
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-1.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-2.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-3.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-4.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-5.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-6.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-7.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-8.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-9.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd10.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd11.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd12.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/simd13.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-2.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-11.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-12.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-13.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-14.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-15.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-16.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-17.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-18.C2
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-19.C2
-rw-r--r--libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c4
-rw-r--r--libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-5.c75
-rw-r--r--libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-6.c75
-rw-r--r--libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-7.c75
-rw-r--r--libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt.c7
-rw-r--r--libgomp/testsuite/libgomp.oacc-c++/c++.exp7
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/collapse-3.c1
-rw-r--r--libstdc++-v3/ChangeLog102
-rwxr-xr-xlibstdc++-v3/configure2
-rw-r--r--libstdc++-v3/doc/Makefile.am2
-rw-r--r--libstdc++-v3/doc/Makefile.in2
-rw-r--r--libstdc++-v3/include/Makefile.am2
-rw-r--r--libstdc++-v3/include/Makefile.in2
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h4
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_types.h2
-rw-r--r--libstdc++-v3/include/bits/stl_pair.h184
-rw-r--r--libstdc++-v3/include/debug/deque38
-rw-r--r--libstdc++-v3/include/debug/forward_list55
-rw-r--r--libstdc++-v3/include/debug/functions.h81
-rw-r--r--libstdc++-v3/include/debug/helper_functions.h210
-rw-r--r--libstdc++-v3/include/debug/list60
-rw-r--r--libstdc++-v3/include/debug/macros.h25
-rw-r--r--libstdc++-v3/include/debug/map.h11
-rw-r--r--libstdc++-v3/include/debug/multimap.h11
-rw-r--r--libstdc++-v3/include/debug/multiset.h11
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.h190
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.tcc50
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.h66
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.tcc16
-rw-r--r--libstdc++-v3/include/debug/set.h11
-rw-r--r--libstdc++-v3/include/debug/stl_iterator.h113
-rw-r--r--libstdc++-v3/include/debug/string49
-rw-r--r--libstdc++-v3/include/debug/unordered_map24
-rw-r--r--libstdc++-v3/include/debug/unordered_set24
-rw-r--r--libstdc++-v3/include/debug/vector35
-rw-r--r--libstdc++-v3/include/experimental/functional2
-rw-r--r--libstdc++-v3/include/std/tuple490
-rw-r--r--libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc108
-rw-r--r--libstdc++-v3/testsuite/20_util/pair/piecewise.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc41
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc282
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc47
270 files changed, 12840 insertions, 2722 deletions
diff --git a/ChangeLog b/ChangeLog
index 1bc0be28483..5ef6a7ad0c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * configure.ac (ospace_frag): Enable for i?86*-*-elfiamcu
+ target.
+ * configure: Regenerate.
+
2015-06-23 Ludovic Courtès <ludo@gnu.org>
* MAINTAINERS (Write After Approval): Add myself.
diff --git a/config/ChangeLog b/config/ChangeLog
index 8d55966bca5..843ad7261e5 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,8 @@
+2015-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * dfp.m4 (enable_decimal_float): Also set to yes for
+ i?86*-*-elfiamcu target.
+
2015-05-27 Jason Merrill <jason@redhat.com>
PR bootstrap/66304
diff --git a/config/dfp.m4 b/config/dfp.m4
index 48683f0f97b..5b29089cec5 100644
--- a/config/dfp.m4
+++ b/config/dfp.m4
@@ -21,7 +21,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'.]) ;;
[
case $1 in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/configure b/configure
index bced9de413e..82e45f3bd39 100755
--- a/configure
+++ b/configure
@@ -6914,7 +6914,7 @@ case "${enable_target_optspace}:${target}" in
:d30v-*)
ospace_frag="config/mt-d30v"
;;
- :m32r-* | :d10v-* | :fr30-*)
+ :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu)
ospace_frag="config/mt-ospace"
;;
no:* | :*)
diff --git a/configure.ac b/configure.ac
index 7c06e6ba9fa..dc77a1baeda 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2560,7 +2560,7 @@ case "${enable_target_optspace}:${target}" in
:d30v-*)
ospace_frag="config/mt-d30v"
;;
- :m32r-* | :d10v-* | :fr30-*)
+ :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu)
ospace_frag="config/mt-ospace"
;;
no:* | :*)
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 976e6894fa2..3f0ba84fc1b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,333 @@
+2015-07-01 Richard Biener <rguenther@suse.de>
+
+ * fold-const.c (fold_binary_loc): Move ~X ^ X -> -1 and
+ (X & Y) ^ Y -> ~X & Y transforms to ...
+ * match.pd: ... here.
+
+2015-07-01 Richard Biener <rguenther@suse.de>
+
+ * genmatch.c (expr::gen_transform): Shortcut re-simplifying
+ of converts to avoid uninteresting noise from the conversion
+ simplifying patterns.
+
+2015-06-30 Sandra Loosemore <sandra@codesourcery.com>
+
+ * config/c6x/c6x.c (try_rename_operands): Do not depend on
+ gcc_assert evaluating its argument for side-effect.
+
+2015-06-30 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ PR target/64833
+ * config/sh/sh.md (casesi_worker_1): Set length to 8 when
+ flag_pic is set.
+
+2015-06-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * lto-streamer-out.c (class DFS): Adjust hash_scc method.
+ (DFS::DFS): Pass this_ref_p and ref_p to hash_scc.
+ (hash_scc): Add this_ref_p and ref_p parameters and pass them
+ to the inner DFS walk.
+
+2015-06-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ * target-insns.def (jump): New targetm instruction pattern.
+ * bb-reorder.c (get_uncond_jump_length): Use targetm.gen_jump
+ instead of gen_jump.
+ (fix_up_crossing_landing_pad): Likewise.
+ (add_labels_and_missing_jumps): Likewise.
+ (fix_crossing_conditional_branches): Likewise.
+ * cfgrtl.c (try_redirect_by_replacing_jump): Likewise.
+ (force_nonfallthru_and_redirect): Likewise.
+ * cse.c (cse_insn): Likewise.
+ * expmed.c (expand_divmod): Likewise.
+ * expr.c (store_expr_with_bounds, expand_expr_real_2): Likewise.
+ * haifa-sched.c (init_before_recovery): Likewise.
+ (sched_create_recovery_edges): Likewise.
+ * ifcvt.c (find_cond_trap): Likewise.
+ * optabs.c (expand_doubleword_shift, expand_doubleword_clz): Likewise.
+ (expand_float, expand_fix): Likewise.
+ * stmt.c (emit_jump): Likewise.
+
+2015-06-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ * defaults.h (HAVE_load_multiple, gen_load_multiple)
+ (HAVE_store_multiple, gen_store_multiple): Delete.
+ * target-insns.def (load_multiple, store_multiple): New targetm
+ instruction patterns.
+ * expr.c (move_block_to_reg, move_block_from_reg): Use them instead
+ of HAVE_*/gen_* interface.
+
+2015-06-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ * defaults.h (HAVE_mem_thread_fence, gen_mem_thread_fence)
+ (HAVE_memory_barrier, gen_memory_barrier, HAVE_mem_signal_fence)
+ (gen_mem_signal_fence): Delete.
+ * target-insns.def (mem_signal_fence, mem_thread_fence)
+ (memory_barrier): New targetm instruction patterns.
+ * optabs.c (expand_mem_thread_fence): Use them instead of HAVE_*/gen_*
+ interface.
+ (expand_mem_signal_fence): Likewise.
+
+2015-06-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ * defaults.h (HAVE_epilogue, gen_epilogue): Delete.
+ * target-insns.def (epilogue, prologue, sibcall_prologue): New
+ targetm instruction patterns.
+ * alias.c (init_alias_analysis): Use them instead of HAVE_*/gen_*
+ interface.
+ * calls.c (expand_call): Likewise.
+ * cfgrtl.c (cfg_layout_finalize): Likewise.
+ * df-scan.c (df_get_entry_block_def_set): Likewise.
+ (df_get_exit_block_use_set): Likewise.
+ * dwarf2cfi.c (pass_dwarf2_frame::gate): Likewise.
+ * final.c (final_start_function): Likewise.
+ * function.c (thread_prologue_and_epilogue_insns): Likewise.
+ (reposition_prologue_and_epilogue_notes): Likewise.
+ * reorg.c (find_end_label): Likewise.
+ * toplev.c (process_options): Likewise.
+
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ * typed-splay-tree.h: New file.
+
+2015-06-30 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR debug/66691
+ * lra-int.h (lra_substitute_pseudo): Add a parameter.
+ (lra_substitute_pseudo_within_insn): Ditto.
+ * lra.c (lra_substitute_pseudo): Add a parameter. Simplify subreg
+ of constant.
+ (lra_substitute_pseudo_within_insn): Add a parameter. Transfer it
+ to lra_substitute_pseudo.
+ * lra-lives.c (process_bb_lives): Add an argument to
+ lra_substitute_pseudo_within_insn call.
+ * lra-constraints.c (inherit_reload_reg, split_reg): Add an
+ argument to lra_substitute_pseudo and
+ lra_substitute_pseudo_within_insn calls.
+ (remove_inheritance_pseudos, undo_optional_reloads): Ditto.
+
+2015-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * configure: Regenerated.
+
+2015-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config.gcc: Support i[34567]86-*-elfiamcu target.
+ * config/i386/iamcu.h: New.
+ * config/i386/i386.opt: Add -miamcu.
+ * doc/invoke.texi: Document -miamcu.
+ * common/config/i386/i386-common.c (ix86_handle_option): Turn
+ off x87/MMX/SSE/AVX codegen for -miamcu.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Define
+ __iamcu/__iamcu__ for -miamcu.
+ * config/i386/i386.h (PREFERRED_STACK_BOUNDARY_DEFAULT): Set
+ to MIN_STACK_BOUNDARY if TARGET_IAMCU is true.
+ (BIGGEST_ALIGNMENT): Set to 32 if TARGET_IAMCU is true.
+ * config/i386/i386.c (ix86_option_override_internal): Ignore and
+ warn -mregparm for Intel MCU. Turn on -mregparm=3 for Intel
+ MCU by default. Default long double to 64-bit for Intel MCU.
+ Turn on -freg-struct-return for Intel MCU. Issue an error when
+ -miamcu is used in 64-bit or x32 mode or if x87, MMX, SSE or
+ AVX is turned on.
+ (function_arg_advance_32): Pass value whose size is no larger
+ than 8 bytes in registers for Intel MCU.
+ (function_arg_32): Likewise.
+ (ix86_return_in_memory): Return value whose size is no larger
+ than 8 bytes in registers for Intel MCU.
+ (iamcu_alignment): New function.
+ (ix86_data_alignment): Call iamcu_alignment if TARGET_IAMCU is
+ true.
+ (ix86_local_alignment): Don't increase alignment for Intel MCU.
+ (x86_field_alignment): Return iamcu_alignment if TARGET_IAMCU is
+ true.
+
+2015-06-30 Marek Polacek <polacek@redhat.com>
+
+ * match.pd (X - (X / Y) * Y): Use convert1 and convert2. Convert
+ both operands of the resulting expression.
+
+ * match.pd (~x | x): Don't use tree_nop_conversion_p. Build
+ the final expression with the operand's type and then convert
+ it to the type of the expression.
+
+2015-06-30 Richard Biener <rguenther@suse.de>
+
+ * fold-const.c (fold_binary_loc): Move ~x & ~y -> ~(x | y) and
+ ~x | ~y -> ~(x & y), (x & CST) ^ (x & CST2) -> (x & CST) | (x & CST2),
+ (X | Y) ^ X -> Y & ~ X, ~X ^ ~Y to X ^ Y and ~X ^ C to X ^ ~C ...
+ * match.pd: ... to patterns here.
+
+2015-06-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/66704
+ * tree-vect-data-refs.c (vect_setup_realignment): Use
+ make_ssa_name for non-SSA name source.
+
+2015-06-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/66702
+ * omp-low.c (simd_clone_adjust): Handle addressable linear
+ or uniform parameters or non-gimple type uniform parameters.
+
+2015-06-30 Richard Biener <rguenther@suse.de>
+
+ * fold-const.c (fold_unary_loc): Move abs(abs(x)) -> abs(x),
+ ~ (-A) to A - 1, ~ (A - 1) or ~ (A + -1) to -A and some cases of
+ ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify to ...
+ * match.pd: ... here.
+ Add a few cases of A - B -> A + (-B) when B "easily" negates.
+ Move (x & y) | x -> x and friends before
+ (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2).
+
+2015-06-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/leon.md (leon_load): Enable for all LEON variants if
+ -mfix-ut699 is not specified.
+ (leon3_load): Rename into...
+ (ut699_load): ...this. Enable for all LEON variants if -mfix-ut699
+ is specified.
+
+2015-06-30 Marek Polacek <polacek@redhat.com>
+
+ * fold-const.c (fold_binary_loc): Move ~X | X folding ...
+ * match.pd: ... here.
+
+2015-06-30 Richard Biener <rguenther@suse.de>
+
+ * target-insns.def (canonicalize_funcptr_for_compare): Add.
+ * fold-const.c (build_range_check): Replace uses of
+ HAVE_canonicalize_funcptr_for_compare.
+ (fold_widened_comparison): Likewise.
+ (fold_sign_changed_comparison): Likewise.
+ * dojump.c: Include "target.h".
+ (do_compare_and_jump): Replace uses of
+ HAVE_canonicalize_funcptr_for_compare and
+ gen_canonicalize_funcptr_for_compare.
+ * expr.c (do_store_flag): Likewise.
+
+2015-06-30 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/66652
+ * tree-parloops.c (try_transform_to_exit_first_loop_alt): Use
+ max_loop_iterations to determine if nit + 1 overflows.
+
+2015-06-30 Richard Biener <rguenther@suse.de>
+
+ * tree-vrp.c (register_edge_assert_for_2): Also register
+ asserts for dominating conversion results.
+
+2015-06-30 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-ssa-loop-ivopts.c (record_sub_use): Don't reset ssa_name
+ field in struct iv.
+
+2015-06-29 Jack Howarth <howarth.at.gcc@gmail.com>
+
+ PR target/66509
+ * configure.ac: Fix filds and fildq test for 64-bit.
+ * configure: Regenerated.
+
+2015-06-29 Nathan Sidwell <nathan@codesourcery.com>
+
+ * config/nvptx/nvptx.md (nvptx_reorg_subreg): New fn, broken out of ...
+ (nvptx_reorg): Here. Keep the non-subreg pieces.
+
+2015-06-29 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/gnu-user.h (GNU_USER_TARGET_ENDFILE_SPEC): Use
+ PIE_SPEC and NO_PIE_SPEC if HAVE_LD_PIE is defined.
+
+2015-06-29 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (*jcc_1): Use %! in asm template.
+ Set attribute "length_nobnd" instead of "length".
+ (*jcc_2): Ditto.
+ (jump): Ditto.
+ (*jcc_1_bnd, *jcc_2_bnd, jump_bnd): Remove insn patterns.
+
+2015-06-29 Sandra Loosemore <sandra@codesourcery.com>
+
+ * config/nios2/nios2.c (nios2_delegitimize_address): Make
+ assert less restrictive.
+
+2015-06-29 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR fortran/66605
+ * cgraphunit.c (cgraph_node::finalize_function): Do not call
+ do_warn_unused_parameter.
+ * function.c (do_warn_unused_parameter): Move from here.
+ * function.h (do_warn_unused_parameter): Do not declare.
+
+2015-06-29 Matthew Wahab <matthew.wahab@arm.com>
+
+ PR target/65697
+ * gcc.target/arm/armv-sync-comp-swap.c: New.
+ * gcc.target/arm/armv-sync-op-acquire.c: New.
+ * gcc.target/arm/armv-sync-op-full.c: New.
+ * gcc.target/arm/armv-sync-op-release.c: New.
+
+2015-06-29 Matthew Wahab <matthew.wahab@arm.com>
+
+ PR target/65697
+ * config/armc/arm.c (arm_split_compare_and_swap): For ARMv8, replace an
+ initial acquire barrier with final barrier.
+
+2015-06-29 Matthew Wahab <matthew.wahab@arm.com>
+
+ PR target/65697
+ * config/armc/arm.c (arm_split_atomic_op): For ARMv8, replace an
+ initial acquire barrier with final barrier.
+
+2015-06-29 Richard Henderson <rth@redhat.com>
+
+ * config/i386/constraints.md (Bf): New constraint.
+ * config/i386/i386-c.c (ix86_target_macros): Define
+ __GCC_ASM_FLAG_OUTPUTS__.
+ * config/i386/i386.c (ix86_md_asm_adjust): Handle =@cc* constraints
+ as flags outputs.
+ * doc/extend.texi (FlagOutputOperands): Document them.
+
+2015-06-29 Jiong Wang <jiong.wang@arm.com>
+
+ * config/arch64/aarch64.md (UNSPEC_TLSLE): New enumeration.
+ * config/arch64/aarch64.md (tlsle_small): Rename to tlsle and use new
+ unspec name.
+ (tlsle_small_<mode>): Rename to tlsle_<mode> and use new unspec name.
+ * config/arch64/aarch64-protos.h (arch64_symbol_type): Rename
+ SYMBOL_SMALL_TPREL to SYMBOL_TLSLE.
+ (aarch64_symbol_context): Ditto.
+ * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): Ditto
+ and use new pattern name.
+ (aarch64_expand_mov_immediate): Ditto.
+ (aarch64_print_operand): Ditto.
+ (aarch64_classify_tls_symbol): Ditto.
+
+2015-06-29 Marek Polacek <polacek@redhat.com>
+ Marc Glisse <marc.glisse@inria.fr>
+
+ * fold-const.c (fold_binary_loc): Move X - (X / Y) * Y -> X % Y to ...
+ * match.pd: ... pattern here.
+
+2015-06-29 Tom de Vries <tom@codesourcery.com>
+
+ * tree-parloops.c (try_transform_to_exit_first_loop_alt): Simplify
+ function structure.
+
+2015-06-29 Matthew Wahab <matthew.wahab@arm.com>
+
+ * doc/invoke.texi (Aarch64 Options, -march): Split out arch and
+ feature description, split out the native option, add a link to
+ the feature documentation, rearrange and slightly rewrite text.
+ (Aarch64 options, -mcpu): Likewise.
+ (Aarch64 options, Feature Modifiers): Add an anchor. Mention
+ +rdma implies Adv. SIMD.
+
+2015-06-29 Marek Polacek <polacek@redhat.com>
+
+ PR c/66322
+ * function.c (stack_protect_epilogue): Remove a cast to int.
+ * doc/invoke.texi: Update -Wswitch-bool description.
+
2015-06-29 Richard Biener <rguenther@suse.de>
* genmatch.c (add_operator): Treat ADDR_EXPR as atom.
diff --git a/gcc/ChangeLog.mas b/gcc/ChangeLog.mas
index 3e73daa5e97..74256747ebe 100644
--- a/gcc/ChangeLog.mas
+++ b/gcc/ChangeLog.mas
@@ -1,3 +1,8 @@
+2015-07-01 Richard Biener <rguenther@suse.de>
+
+ Merge from trunk r225116 through r225225.
+ * match-bitwise.pd: Removed and merged remains into match.pd.
+
2015-06-29 Richard Biener <rguenther@suse.de>
Merge from trunk r221894 through r225115.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index e19b2f675ab..d63b57da5f2 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20150629
+20150701
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 89d8898e58d..db794204330 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,15 @@
+2015-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/63310
+ * gcc-interface/utils.c (gnat_write_global_declarations): Always
+ build the dummy global variable if code was generated.
+
+2015-06-29 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR fortran/66605
+ * gcc-interface/misc.c (gnat_post_options): No need to disable
+ warn_unused_parameter anymore.
+
2015-06-26 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (Handled_Sequence_Of_Statements_to_gnu): When
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 2f397ba1fe7..fec71999ac3 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -262,9 +262,6 @@ gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED)
sorry ("-fexcess-precision=standard for Ada");
flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
- /* ??? The warning machinery is outsmarted by Ada. */
- warn_unused_parameter = 0;
-
/* No psABI change warnings for Ada. */
warn_psabi = 0;
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index ab5b9e0bc45..a02dc67a305 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -5202,8 +5202,9 @@ gnat_write_global_declarations (void)
tree iter;
/* If we have declared types as used at the global level, insert them in
- the global hash table. We use a dummy variable for this purpose. */
- if (types_used_by_cur_var_decl && !types_used_by_cur_var_decl->is_empty ())
+ the global hash table. We use a dummy variable for this purpose, but
+ we need to build it unconditionally to avoid -fcompare-debug issues. */
+ if (first_global_object_name)
{
struct varpool_node *node;
char *label;
@@ -5218,11 +5219,12 @@ gnat_write_global_declarations (void)
node->definition = 1;
node->force_output = 1;
- while (!types_used_by_cur_var_decl->is_empty ())
- {
- tree t = types_used_by_cur_var_decl->pop ();
- types_used_by_var_decl_insert (t, dummy_global);
- }
+ if (types_used_by_cur_var_decl)
+ while (!types_used_by_cur_var_decl->is_empty ())
+ {
+ tree t = types_used_by_cur_var_decl->pop ();
+ types_used_by_var_decl_insert (t, dummy_global);
+ }
}
/* Output debug information for all global type declarations first. This
diff --git a/gcc/alias.c b/gcc/alias.c
index ca2082e7e65..3e75b91b63d 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -3038,6 +3038,14 @@ init_alias_analysis (void)
rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
rpo_cnt = pre_and_rev_post_order_compute (NULL, rpo, false);
+ /* The prologue/epilogue insns are not threaded onto the
+ insn chain until after reload has completed. Thus,
+ there is no sense wasting time checking if INSN is in
+ the prologue/epilogue until after reload has completed. */
+ bool could_be_prologue_epilogue = ((targetm.have_prologue ()
+ || targetm.have_epilogue ())
+ && reload_completed);
+
pass = 0;
do
{
@@ -3076,17 +3084,7 @@ init_alias_analysis (void)
{
rtx note, set;
-#if defined (HAVE_prologue)
- static const bool prologue = true;
-#else
- static const bool prologue = false;
-#endif
-
- /* The prologue/epilogue insns are not threaded onto the
- insn chain until after reload has completed. Thus,
- there is no sense wasting time checking if INSN is in
- the prologue/epilogue until after reload has completed. */
- if ((prologue || HAVE_epilogue) && reload_completed
+ if (could_be_prologue_epilogue
&& prologue_epilogue_contains (insn))
continue;
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index dd98527b572..84c91524755 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -1385,7 +1385,7 @@ get_uncond_jump_length (void)
start_sequence ();
rtx_code_label *label = emit_label (gen_label_rtx ());
- rtx_insn *jump = emit_jump_insn (gen_jump (label));
+ rtx_insn *jump = emit_jump_insn (targetm.gen_jump (label));
length = get_attr_min_length (jump);
end_sequence ();
@@ -1420,7 +1420,7 @@ fix_up_crossing_landing_pad (eh_landing_pad old_lp, basic_block old_bb)
post_bb = BLOCK_FOR_INSN (old_lp->landing_pad);
post_bb = single_succ (post_bb);
rtx_code_label *post_label = block_label (post_bb);
- jump = emit_jump_insn (gen_jump (post_label));
+ jump = emit_jump_insn (targetm.gen_jump (post_label));
JUMP_LABEL (jump) = post_label;
/* Create new basic block to be dest for lp. */
@@ -1766,7 +1766,7 @@ add_labels_and_missing_jumps (vec<edge> crossing_edges)
/* Make sure there's only one successor. */
gcc_assert (single_succ_p (src));
- new_jump = emit_jump_insn_after (gen_jump (label), BB_END (src));
+ new_jump = emit_jump_insn_after (targetm.gen_jump (label), BB_END (src));
BB_END (src) = new_jump;
JUMP_LABEL (new_jump) = label;
LABEL_NUSES (label) += 1;
@@ -2082,7 +2082,7 @@ fix_crossing_conditional_branches (void)
gcc_assert (GET_CODE (old_label) == LABEL_REF);
old_jump_target = old_jump_insn->jump_target ();
new_jump = as_a <rtx_jump_insn *>
- (emit_jump_insn (gen_jump (old_jump_target)));
+ (emit_jump_insn (targetm.gen_jump (old_jump_target)));
new_jump->set_jump_target (old_jump_target);
last_bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index ffad035ffef..27ae6064d22 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,32 @@
+2015-06-30 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement N4197 - Adding u8 character literals
+ * c-family/c-ada-spec.c (print_ada_macros): Treat CPP_UTF8CHAR like
+ CPP_CHAR.
+ * c-family/c-common.c (c_parse_error): Print CPP_UTF8CHAR and
+ CPP_UTF8CHAR_USERDEF tokens.
+ * c-family/c-lex.c (c_lex_with_flags): Treat CPP_UTF8CHAR_USERDEF
+ and CPP_UTF8CHAR tokens.
+ (lex_charconst): Treat CPP_UTF8CHAR token.
+
+2015-06-29 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR fortran/66605
+ * c-common.c (do_warn_unused_parameter): Move here.
+ * c-common.h (do_warn_unused_parameter): Declare.
+
+2015-06-29 Marek Polacek <polacek@redhat.com>
+
+ PR c/66322
+ * c-common.c (check_case_bounds): Add bool * parameter. Set
+ OUTSIDE_RANGE_P.
+ (c_add_case_label): Add bool * parameter. Pass it down to
+ check_case_bounds.
+ (c_do_switch_warnings): Add bool parameters. Implement -Wswitch-bool
+ warning here.
+ * c-common.h (c_add_case_label, c_do_switch_warnings): Update
+ declarations.
+
2015-06-27 Marek Polacek <polacek@redhat.com>
* c-common.c (check_main_parameter_types): Use VECTOR_TYPE_P
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index ef3c5e3ae2b..41d612fc467 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -249,6 +249,7 @@ print_ada_macros (pretty_printer *pp, cpp_hashnode **macros, int max_ada_macros)
case CPP_WCHAR:
case CPP_CHAR16:
case CPP_CHAR32:
+ case CPP_UTF8CHAR:
case CPP_NAME:
case CPP_STRING:
case CPP_NUMBER:
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 06d2abcd451..835fc2ce190 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -306,7 +306,8 @@ struct visibility_flags visibility_options;
static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool);
static tree check_case_value (location_t, tree);
-static bool check_case_bounds (location_t, tree, tree, tree *, tree *);
+static bool check_case_bounds (location_t, tree, tree, tree *, tree *,
+ bool *);
static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
@@ -3633,13 +3634,15 @@ check_case_value (location_t loc, tree value)
bound of the case label, and CASE_HIGH_P is the upper bound or NULL
if the case is not a case range.
The caller has to make sure that we are not called with NULL for
- CASE_LOW_P (i.e. the default case).
+ CASE_LOW_P (i.e. the default case). OUTSIDE_RANGE_P says whether there
+ was a case value that doesn't fit into the range of the ORIG_TYPE.
Returns true if the case label is in range of ORIG_TYPE (saturated or
untouched) or false if the label is out of range. */
static bool
check_case_bounds (location_t loc, tree type, tree orig_type,
- tree *case_low_p, tree *case_high_p)
+ tree *case_low_p, tree *case_high_p,
+ bool *outside_range_p)
{
tree min_value, max_value;
tree case_low = *case_low_p;
@@ -3658,6 +3661,7 @@ check_case_bounds (location_t loc, tree type, tree orig_type,
{
warning_at (loc, 0, "case label value is less than minimum value "
"for type");
+ *outside_range_p = true;
return false;
}
@@ -3666,6 +3670,7 @@ check_case_bounds (location_t loc, tree type, tree orig_type,
&& tree_int_cst_compare (case_high, max_value) > 0)
{
warning_at (loc, 0, "case label value exceeds maximum value for type");
+ *outside_range_p = true;
return false;
}
@@ -3675,6 +3680,7 @@ check_case_bounds (location_t loc, tree type, tree orig_type,
{
warning_at (loc, 0, "lower value in case label range"
" less than minimum value for type");
+ *outside_range_p = true;
case_low = min_value;
}
@@ -3684,6 +3690,7 @@ check_case_bounds (location_t loc, tree type, tree orig_type,
{
warning_at (loc, 0, "upper value in case label range"
" exceeds maximum value for type");
+ *outside_range_p = true;
case_high = max_value;
}
@@ -6391,13 +6398,14 @@ case_compare (splay_tree_key k1, splay_tree_key k2)
HIGH_VALUE is NULL_TREE, then case label was declared using the
usual C/C++ syntax, rather than the GNU case range extension.
CASES is a tree containing all the case ranges processed so far;
- COND is the condition for the switch-statement itself. Returns the
- CASE_LABEL_EXPR created, or ERROR_MARK_NODE if no CASE_LABEL_EXPR
- is created. */
+ COND is the condition for the switch-statement itself.
+ OUTSIDE_RANGE_P says whether there was a case value that doesn't
+ fit into the range of the ORIG_TYPE. Returns the CASE_LABEL_EXPR
+ created, or ERROR_MARK_NODE if no CASE_LABEL_EXPR is created. */
tree
c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type,
- tree low_value, tree high_value)
+ tree low_value, tree high_value, bool *outside_range_p)
{
tree type;
tree label;
@@ -6458,7 +6466,8 @@ c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type,
don't insert the case label and return NULL_TREE. */
if (low_value
&& !check_case_bounds (loc, type, orig_type,
- &low_value, high_value ? &high_value : NULL))
+ &low_value, high_value ? &high_value : NULL,
+ outside_range_p))
return NULL_TREE;
/* Look up the LOW_VALUE in the table of case labels we already
@@ -6619,13 +6628,15 @@ match_case_to_enum (splay_tree_node node, void *data)
void
c_do_switch_warnings (splay_tree cases, location_t switch_location,
- tree type, tree cond)
+ tree type, tree cond, bool bool_cond_p,
+ bool outside_range_p)
{
splay_tree_node default_node;
splay_tree_node node;
tree chain;
- if (!warn_switch && !warn_switch_enum && !warn_switch_default)
+ if (!warn_switch && !warn_switch_enum && !warn_switch_default
+ && !warn_switch_bool)
return;
default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
@@ -6633,6 +6644,52 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
warning_at (switch_location, OPT_Wswitch_default,
"switch missing default case");
+ /* There are certain cases where -Wswitch-bool warnings aren't
+ desirable, such as
+ switch (boolean)
+ {
+ case true: ...
+ case false: ...
+ }
+ so be careful here. */
+ if (warn_switch_bool && bool_cond_p)
+ {
+ splay_tree_node min_node;
+ /* If there's a default node, it's also the value with the minimal
+ key. So look at the penultimate key (if any). */
+ if (default_node)
+ min_node = splay_tree_successor (cases, (splay_tree_key) NULL);
+ else
+ min_node = splay_tree_min (cases);
+ tree min = min_node ? (tree) min_node->key : NULL_TREE;
+
+ splay_tree_node max_node = splay_tree_max (cases);
+ /* This might be a case range, so look at the value with the
+ maximal key and then check CASE_HIGH. */
+ tree max = max_node ? (tree) max_node->value : NULL_TREE;
+ if (max)
+ max = CASE_HIGH (max) ? CASE_HIGH (max) : CASE_LOW (max);
+
+ /* If there's a case value > 1 or < 0, that is outside bool
+ range, warn. */
+ if (outside_range_p
+ || (max && wi::gts_p (max, 1))
+ || (min && wi::lts_p (min, 0))
+ /* And handle the
+ switch (boolean)
+ {
+ case true: ...
+ case false: ...
+ default: ...
+ }
+ case, where we want to warn. */
+ || (default_node
+ && max && wi::eq_p (max, 1)
+ && min && wi::eq_p (min, 0)))
+ warning_at (switch_location, OPT_Wswitch_bool,
+ "switch condition has boolean value");
+ }
+
/* From here on, we only care about about enumerated types. */
if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
return;
@@ -10199,7 +10256,8 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
else if (token_type == CPP_CHAR
|| token_type == CPP_WCHAR
|| token_type == CPP_CHAR16
- || token_type == CPP_CHAR32)
+ || token_type == CPP_CHAR32
+ || token_type == CPP_UTF8CHAR)
{
unsigned int val = TREE_INT_CST_LOW (value);
const char *prefix;
@@ -10218,6 +10276,9 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
case CPP_CHAR32:
prefix = "U";
break;
+ case CPP_UTF8CHAR:
+ prefix = "u8";
+ break;
}
if (val <= UCHAR_MAX && ISGRAPH (val))
@@ -10232,7 +10293,8 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
else if (token_type == CPP_CHAR_USERDEF
|| token_type == CPP_WCHAR_USERDEF
|| token_type == CPP_CHAR16_USERDEF
- || token_type == CPP_CHAR32_USERDEF)
+ || token_type == CPP_CHAR32_USERDEF
+ || token_type == CPP_UTF8CHAR_USERDEF)
message = catenate_messages (gmsgid,
" before user-defined character literal");
else if (token_type == CPP_STRING_USERDEF
@@ -12046,6 +12108,23 @@ do_warn_double_promotion (tree result_type, tree type1, tree type2,
warning_at (loc, OPT_Wdouble_promotion, gmsgid, source_type, result_type);
}
+/* Possibly warn about unused parameters. */
+
+void
+do_warn_unused_parameter (tree fn)
+{
+ tree decl;
+
+ for (decl = DECL_ARGUMENTS (fn);
+ decl; decl = DECL_CHAIN (decl))
+ if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
+ && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)
+ && !TREE_NO_WARNING (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wunused_parameter,
+ "unused parameter %qD", decl);
+}
+
+
/* Setup a TYPE_DECL node as a typedef representation.
X is a TYPE_DECL for a typedef statement. Create a brand new
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 8951c3f9fb6..dd9839682c2 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -946,9 +946,11 @@ extern tree boolean_increment (enum tree_code, tree);
extern int case_compare (splay_tree_key, splay_tree_key);
-extern tree c_add_case_label (location_t, splay_tree, tree, tree, tree, tree);
+extern tree c_add_case_label (location_t, splay_tree, tree, tree, tree, tree,
+ bool *);
-extern void c_do_switch_warnings (splay_tree, location_t, tree, tree);
+extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool,
+ bool);
extern tree build_function_call (location_t, tree, tree);
@@ -1043,6 +1045,7 @@ extern void warn_for_sign_compare (location_t,
tree op0, tree op1,
tree result_type,
enum tree_code resultcode);
+extern void do_warn_unused_parameter (tree);
extern void do_warn_double_promotion (tree, tree, tree, const char *,
location_t);
extern void set_underlying_type (tree);
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 9c56832219b..aa5d6e2313f 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -536,6 +536,7 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
case CPP_WCHAR_USERDEF:
case CPP_CHAR16_USERDEF:
case CPP_CHAR32_USERDEF:
+ case CPP_UTF8CHAR_USERDEF:
{
tree literal;
cpp_token temp_tok = *tok;
@@ -553,6 +554,7 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
case CPP_WCHAR:
case CPP_CHAR16:
case CPP_CHAR32:
+ case CPP_UTF8CHAR:
*value = lex_charconst (tok);
break;
@@ -1250,6 +1252,8 @@ lex_charconst (const cpp_token *token)
type = char32_type_node;
else if (token->type == CPP_CHAR16)
type = char16_type_node;
+ else if (token->type == CPP_UTF8CHAR)
+ type = char_type_node;
/* In C, a character constant has type 'int'.
In C++ 'char', but multi-char charconsts have type 'int'. */
else if (!c_dialect_cxx () || chars_seen > 1)
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index edba3f1f51b..15c2303c2de 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,17 @@
+2015-06-29 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR fortran/66605
+ * c-decl.c (finish_function): Call do_warn_unused_parameter.
+
+2015-06-29 Marek Polacek <polacek@redhat.com>
+
+ PR c/66322
+ * c-typeck.c (struct c_switch): Add BOOL_COND_P and OUTSIDE_RANGE_P.
+ (c_start_case): Set BOOL_COND_P and OUTSIDE_RANGE_P. Don't warn
+ about -Wswitch-bool here.
+ (do_case): Update c_add_case_label call.
+ (c_finish_case): Update c_do_switch_warnings call.
+
2015-06-27 Marek Polacek <polacek@redhat.com>
* c-typeck.c: Use VECTOR_TYPE_P throughout.
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 6aac8c36157..383f0a766bf 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -9028,6 +9028,10 @@ finish_function (void)
function. */
maybe_warn_unused_local_typedefs ();
+ /* Possibly warn about unused parameters. */
+ if (warn_unused_parameter)
+ do_warn_unused_parameter (fndecl);
+
/* Store the end of the function, so that we get good line number
info for the epilogue. */
cfun->function_end_locus = input_location;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 8e2696a7a21..6ea35137d50 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9525,6 +9525,14 @@ struct c_switch {
/* The next node on the stack. */
struct c_switch *next;
+
+ /* Remember whether the controlling expression had boolean type
+ before integer promotions for the sake of -Wswitch-bool. */
+ bool bool_cond_p;
+
+ /* Remember whether there was a case value that is outside the
+ range of the ORIG_TYPE. */
+ bool outside_range_p;
};
/* A stack of the currently active switch statements. The innermost
@@ -9538,7 +9546,7 @@ struct c_switch *c_switch_stack;
/* Start a C switch statement, testing expression EXP. Return the new
SWITCH_EXPR. SWITCH_LOC is the location of the `switch'.
SWITCH_COND_LOC is the location of the switch's condition.
- EXPLICIT_CAST_P is true if the expression EXP has explicit cast. */
+ EXPLICIT_CAST_P is true if the expression EXP has an explicit cast. */
tree
c_start_case (location_t switch_loc,
@@ -9546,6 +9554,7 @@ c_start_case (location_t switch_loc,
tree exp, bool explicit_cast_p)
{
tree orig_type = error_mark_node;
+ bool bool_cond_p = false;
struct c_switch *cs;
if (exp != error_mark_node)
@@ -9575,8 +9584,7 @@ c_start_case (location_t switch_loc,
/* Explicit cast to int suppresses this warning. */
&& !(TREE_CODE (type) == INTEGER_TYPE
&& explicit_cast_p))
- warning_at (switch_cond_loc, OPT_Wswitch_bool,
- "switch condition has boolean value");
+ bool_cond_p = true;
if (!in_system_header_at (input_location)
&& (type == long_integer_type_node
@@ -9600,6 +9608,8 @@ c_start_case (location_t switch_loc,
cs->orig_type = orig_type;
cs->cases = splay_tree_new (case_compare, NULL, NULL);
cs->bindings = c_get_switch_bindings ();
+ cs->bool_cond_p = bool_cond_p;
+ cs->outside_range_p = false;
cs->next = c_switch_stack;
c_switch_stack = cs;
@@ -9646,7 +9656,8 @@ do_case (location_t loc, tree low_value, tree high_value)
label = c_add_case_label (loc, c_switch_stack->cases,
SWITCH_COND (c_switch_stack->switch_expr),
c_switch_stack->orig_type,
- low_value, high_value);
+ low_value, high_value,
+ &c_switch_stack->outside_range_p);
if (label == error_mark_node)
label = NULL_TREE;
return label;
@@ -9667,7 +9678,8 @@ c_finish_case (tree body, tree type)
switch_location = EXPR_LOCATION (cs->switch_expr);
c_do_switch_warnings (cs->cases, switch_location,
type ? type : TREE_TYPE (cs->switch_expr),
- SWITCH_COND (cs->switch_expr));
+ SWITCH_COND (cs->switch_expr),
+ cs->bool_cond_p, cs->outside_range_p);
/* Pop the stack. */
c_switch_stack = cs->next;
diff --git a/gcc/calls.c b/gcc/calls.c
index a8a1d0e5ac4..e97c356ca80 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -2783,13 +2783,8 @@ expand_call (tree exp, rtx target, int ignore)
try_tail_call = 0;
/* Rest of purposes for tail call optimizations to fail. */
- if (
-#ifdef HAVE_sibcall_epilogue
- !HAVE_sibcall_epilogue
-#else
- 1
-#endif
- || !try_tail_call
+ if (!try_tail_call
+ || !targetm.have_sibcall_epilogue ()
/* Doing sibling call optimization needs some work, since
structure_value_addr can be allocated on the stack.
It does not seem worth the effort since few optimizable
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 2e33dda2f81..4a711b3aa4f 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -1117,7 +1117,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
rtx label;
rtx_jump_table_data *table;
- emit_jump_insn_after_noloc (gen_jump (target_label), insn);
+ emit_jump_insn_after_noloc (targetm.gen_jump (target_label), insn);
JUMP_LABEL (BB_END (src)) = target_label;
LABEL_NUSES (target_label)++;
if (dump_file)
@@ -1708,7 +1708,8 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
else
{
rtx_code_label *label = block_label (target);
- emit_jump_insn_after_setloc (gen_jump (label), BB_END (jump_block), loc);
+ emit_jump_insn_after_setloc (targetm.gen_jump (label),
+ BB_END (jump_block), loc);
JUMP_LABEL (BB_END (jump_block)) = label;
LABEL_NUSES (label)++;
}
@@ -4324,7 +4325,7 @@ cfg_layout_finalize (void)
#endif
force_one_exit_fallthru ();
rtl_register_cfg_hooks ();
- if (reload_completed && !HAVE_epilogue)
+ if (reload_completed && !targetm.have_epilogue ())
fixup_fallthru_exit_predecessor ();
fixup_reorder_chain ();
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 1b356467b72..7e78bf78915 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -472,10 +472,6 @@ cgraph_node::finalize_function (tree decl, bool no_collect)
if (!TREE_ASM_WRITTEN (decl))
(*debug_hooks->deferred_inline_function) (decl);
- /* Possibly warn about unused parameters. */
- if (warn_unused_parameter)
- do_warn_unused_parameter (decl);
-
if (!no_collect)
ggc_collect ();
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 0f8c3e1df04..79b2472dc75 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -223,7 +223,7 @@ along with GCC; see the file COPYING3. If not see
bool
ix86_handle_option (struct gcc_options *opts,
- struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ struct gcc_options *opts_set,
const struct cl_decoded_option *decoded,
location_t loc)
{
@@ -232,6 +232,20 @@ ix86_handle_option (struct gcc_options *opts,
switch (code)
{
+ case OPT_miamcu:
+ if (value)
+ {
+ /* Turn off x87/MMX/SSE/AVX codegen for -miamcu. */
+ opts->x_target_flags &= ~MASK_80387;
+ opts_set->x_target_flags |= MASK_80387;
+ opts->x_ix86_isa_flags &= ~(OPTION_MASK_ISA_MMX_UNSET
+ | OPTION_MASK_ISA_SSE_UNSET);
+ opts->x_ix86_isa_flags_explicit |= (OPTION_MASK_ISA_MMX_UNSET
+ | OPTION_MASK_ISA_SSE_UNSET);
+
+ }
+ return true;
+
case OPT_mmmx:
if (value)
{
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 805638d7261..2b3af82be94 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1389,6 +1389,9 @@ x86_64-*-darwin*)
tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc"
tm_file="${tm_file} ${cpu_type}/darwin64.h"
;;
+i[34567]86-*-elfiamcu)
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/iamcu.h"
+ ;;
i[34567]86-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
;;
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 2c623cc145c..4062c2736ae 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -72,7 +72,7 @@ enum aarch64_symbol_context
SYMBOL_SMALL_TLSGD
SYMBOL_SMALL_TLSDESC
SYMBOL_SMALL_GOTTPREL
- SYMBOL_SMALL_TPREL
+ SYMBOL_TLSLE
Each of of these represents a thread-local symbol, and corresponds to the
thread local storage relocation operator for the symbol being referred to.
@@ -107,9 +107,9 @@ enum aarch64_symbol_type
SYMBOL_SMALL_TLSGD,
SYMBOL_SMALL_TLSDESC,
SYMBOL_SMALL_GOTTPREL,
- SYMBOL_SMALL_TPREL,
SYMBOL_TINY_ABSOLUTE,
SYMBOL_TINY_GOT,
+ SYMBOL_TLSLE,
SYMBOL_FORCE_TO_MEM
};
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index f130f8dea1d..0079c82b0f8 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1059,14 +1059,14 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
return;
}
- case SYMBOL_SMALL_TPREL:
+ case SYMBOL_TLSLE:
{
rtx tp = aarch64_load_tp (NULL);
if (GET_MODE (dest) != Pmode)
tp = gen_lowpart (GET_MODE (dest), tp);
- emit_insn (gen_tlsle_small (dest, tp, imm));
+ emit_insn (gen_tlsle (dest, tp, imm));
set_unique_reg_note (get_last_insn (), REG_EQUIV, imm);
return;
}
@@ -1619,9 +1619,9 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
}
/* FALLTHRU */
- case SYMBOL_SMALL_TPREL:
case SYMBOL_SMALL_ABSOLUTE:
case SYMBOL_TINY_ABSOLUTE:
+ case SYMBOL_TLSLE:
aarch64_load_symref_appropriately (dest, imm, sty);
return;
@@ -4504,7 +4504,7 @@ aarch64_print_operand (FILE *f, rtx x, char code)
asm_fprintf (asm_out_file, ":gottprel:");
break;
- case SYMBOL_SMALL_TPREL:
+ case SYMBOL_TLSLE:
asm_fprintf (asm_out_file, ":tprel:");
break;
@@ -4537,7 +4537,7 @@ aarch64_print_operand (FILE *f, rtx x, char code)
asm_fprintf (asm_out_file, ":gottprel_lo12:");
break;
- case SYMBOL_SMALL_TPREL:
+ case SYMBOL_TLSLE:
asm_fprintf (asm_out_file, ":tprel_lo12_nc:");
break;
@@ -4555,7 +4555,7 @@ aarch64_print_operand (FILE *f, rtx x, char code)
switch (aarch64_classify_symbolic_expression (x, SYMBOL_CONTEXT_ADR))
{
- case SYMBOL_SMALL_TPREL:
+ case SYMBOL_TLSLE:
asm_fprintf (asm_out_file, ":tprel_hi12:");
break;
default:
@@ -7635,7 +7635,7 @@ aarch64_classify_tls_symbol (rtx x)
return SYMBOL_SMALL_GOTTPREL;
case TLS_MODEL_LOCAL_EXEC:
- return SYMBOL_SMALL_TPREL;
+ return SYMBOL_TLSLE;
case TLS_MODEL_EMULATED:
case TLS_MODEL_NONE:
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index a1722684bc5..2d56a75b43f 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -117,6 +117,7 @@
UNSPEC_ST4_LANE
UNSPEC_TLS
UNSPEC_TLSDESC
+ UNSPEC_TLSLE
UNSPEC_USHL_2S
UNSPEC_VSTRUCTDUMMY
UNSPEC_SP_SET
@@ -4446,27 +4447,25 @@
(set_attr "length" "8")]
)
-(define_expand "tlsle_small"
+(define_expand "tlsle"
[(set (match_operand 0 "register_operand" "=r")
(unspec [(match_operand 1 "register_operand" "r")
(match_operand 2 "aarch64_tls_le_symref" "S")]
- UNSPEC_GOTSMALLTLS))]
+ UNSPEC_TLSLE))]
""
{
machine_mode mode = GET_MODE (operands[0]);
emit_insn ((mode == DImode
- ? gen_tlsle_small_di
- : gen_tlsle_small_si) (operands[0],
- operands[1],
- operands[2]));
+ ? gen_tlsle_di
+ : gen_tlsle_si) (operands[0], operands[1], operands[2]));
DONE;
})
-(define_insn "tlsle_small_<mode>"
+(define_insn "tlsle_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_operand:P 1 "register_operand" "r")
(match_operand 2 "aarch64_tls_le_symref" "S")]
- UNSPEC_GOTSMALLTLS))]
+ UNSPEC_TLSLE))]
""
"add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
[(set_attr "type" "alu_sreg")
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 9f300415ede..c2dce95e611 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -27614,6 +27614,8 @@ arm_split_compare_and_swap (rtx operands[])
scratch = operands[7];
mode = GET_MODE (mem);
+ bool is_armv8_sync = arm_arch8 && is_mm_sync (mod_s);
+
bool use_acquire = TARGET_HAVE_LDACQ
&& !(is_mm_relaxed (mod_s) || is_mm_consume (mod_s)
|| is_mm_release (mod_s));
@@ -27622,6 +27624,11 @@ arm_split_compare_and_swap (rtx operands[])
&& !(is_mm_relaxed (mod_s) || is_mm_consume (mod_s)
|| is_mm_acquire (mod_s));
+ /* For ARMv8, the load-acquire is too weak for __sync memory orders. Instead,
+ a full barrier is emitted after the store-release. */
+ if (is_armv8_sync)
+ use_acquire = false;
+
/* Checks whether a barrier is needed and emits one accordingly. */
if (!(use_acquire || use_release))
arm_pre_atomic_barrier (mod_s);
@@ -27662,7 +27669,8 @@ arm_split_compare_and_swap (rtx operands[])
emit_label (label2);
/* Checks whether a barrier is needed and emits one accordingly. */
- if (!(use_acquire || use_release))
+ if (is_armv8_sync
+ || !(use_acquire || use_release))
arm_post_atomic_barrier (mod_s);
if (is_mm_relaxed (mod_f))
@@ -27679,6 +27687,8 @@ arm_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
rtx_code_label *label;
rtx x;
+ bool is_armv8_sync = arm_arch8 && is_mm_sync (model);
+
bool use_acquire = TARGET_HAVE_LDACQ
&& !(is_mm_relaxed (model) || is_mm_consume (model)
|| is_mm_release (model));
@@ -27687,6 +27697,11 @@ arm_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
&& !(is_mm_relaxed (model) || is_mm_consume (model)
|| is_mm_acquire (model));
+ /* For ARMv8, a load-acquire is too weak for __sync memory orders. Instead,
+ a full barrier is emitted after the store-release. */
+ if (is_armv8_sync)
+ use_acquire = false;
+
/* Checks whether a barrier is needed and emits one accordingly. */
if (!(use_acquire || use_release))
arm_pre_atomic_barrier (model);
@@ -27757,7 +27772,8 @@ arm_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
emit_unlikely_jump (gen_cbranchsi4 (x, cond, const0_rtx, label));
/* Checks whether a barrier is needed and emits one accordingly. */
- if (!(use_acquire || use_release))
+ if (is_armv8_sync
+ || !(use_acquire || use_release))
arm_post_atomic_barrier (model);
}
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index b76a268ddb4..159335d75c9 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -3450,6 +3450,7 @@ try_rename_operands (rtx_insn *head, rtx_insn *tail, unit_req_table reqs,
int best_reg, old_reg;
vec<du_head_p> involved_chains = vNULL;
unit_req_table new_reqs;
+ bool ok;
for (i = 0, tmp_mask = op_mask; tmp_mask; i++)
{
@@ -3516,7 +3517,8 @@ try_rename_operands (rtx_insn *head, rtx_insn *tail, unit_req_table reqs,
best_reg =
find_rename_reg (this_head, super_class, &unavailable, old_reg, true);
- gcc_assert (regrename_do_replace (this_head, best_reg));
+ ok = regrename_do_replace (this_head, best_reg);
+ gcc_assert (ok);
count_unit_reqs (new_reqs, head, PREV_INSN (tail));
merge_unit_reqs (new_reqs);
@@ -3529,7 +3531,10 @@ try_rename_operands (rtx_insn *head, rtx_insn *tail, unit_req_table reqs,
unit_req_imbalance (reqs), unit_req_imbalance (new_reqs));
}
if (unit_req_imbalance (new_reqs) > unit_req_imbalance (reqs))
- gcc_assert (regrename_do_replace (this_head, old_reg));
+ {
+ ok = regrename_do_replace (this_head, old_reg);
+ gcc_assert (ok);
+ }
else
memcpy (reqs, new_reqs, sizeof (unit_req_table));
diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h
index 2fcb55dbdab..5b3576bdf95 100644
--- a/gcc/config/gnu-user.h
+++ b/gcc/config/gnu-user.h
@@ -67,11 +67,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
object constructed before entering `main', followed by a normal
GNU userspace "finalizer" file, `crtn.o'. */
+#if defined HAVE_LD_PIE
+#define GNU_USER_TARGET_ENDFILE_SPEC \
+ "%{fvtable-verify=none:%s; \
+ fvtable-verify=preinit:vtv_end_preinit.o%s; \
+ fvtable-verify=std:vtv_end.o%s} \
+ %{shared:crtendS.o%s;: %{" PIE_SPEC ":crtendS.o%s} \
+ %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s"
+#else
#define GNU_USER_TARGET_ENDFILE_SPEC \
"%{fvtable-verify=none:%s; \
fvtable-verify=preinit:vtv_end_preinit.o%s; \
fvtable-verify=std:vtv_end.o%s} \
%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+#endif
#undef ENDFILE_SPEC
#define ENDFILE_SPEC GNU_USER_TARGET_ENDFILE_SPEC
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index c718bc10017..2861d8dfdd2 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -146,11 +146,16 @@
"@internal Lower SSE register when avoiding REX prefix and all SSE registers otherwise.")
;; We use the B prefix to denote any number of internal operands:
+;; f FLAGS_REG
;; g GOT memory operand.
;; s Sibcall memory operand, not valid for TARGET_X32
;; w Call memory operand, not valid for TARGET_X32
;; z Constant call address operand.
+(define_constraint "Bf"
+ "@internal Flags register operand."
+ (match_operand 0 "flags_reg_operand"))
+
(define_constraint "Bg"
"@internal GOT memory operand."
(match_operand 0 "GOT_memory_operand"))
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 28444f9039a..304ce551d20 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -425,6 +425,11 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__CLWB__");
if (isa_flag & OPTION_MASK_ISA_MWAITX)
def_or_undef (parse_in, "__MWAITX__");
+ if (TARGET_IAMCU)
+ {
+ def_or_undef (parse_in, "__iamcu");
+ def_or_undef (parse_in, "__iamcu__");
+ }
}
@@ -560,6 +565,8 @@ ix86_target_macros (void)
cpp_define_formatted (parse_in, "__ATOMIC_HLE_ACQUIRE=%d", IX86_HLE_ACQUIRE);
cpp_define_formatted (parse_in, "__ATOMIC_HLE_RELEASE=%d", IX86_HLE_RELEASE);
+ cpp_define (parse_in, "__GCC_ASM_FLAG_OUTPUTS__");
+
ix86_target_macros_internal (ix86_isa_flags,
ix86_arch,
ix86_tune,
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 95986006ec8..7d26e8c2bd0 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3433,6 +3433,10 @@ ix86_option_override_internal (bool main_args_p,
|| TARGET_16BIT_P (opts->x_ix86_isa_flags))
opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32;
#endif
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ && TARGET_IAMCU_P (opts->x_target_flags))
+ sorry ("Intel MCU psABI isn%'t supported in %s mode",
+ TARGET_X32_P (opts->x_ix86_isa_flags) ? "x32" : "64-bit");
}
#endif
@@ -3817,6 +3821,20 @@ ix86_option_override_internal (bool main_args_p,
if (TARGET_X32 && (ix86_isa_flags & OPTION_MASK_ISA_MPX))
error ("Intel MPX does not support x32");
+ if (TARGET_IAMCU_P (opts->x_target_flags))
+ {
+ /* Verify that x87/MMX/SSE/AVX is off for -miamcu. */
+ if (TARGET_80387_P (opts->x_target_flags))
+ sorry ("X87 FPU isn%'t supported in Intel MCU psABI");
+ else if ((opts->x_ix86_isa_flags & (OPTION_MASK_ISA_MMX
+ | OPTION_MASK_ISA_SSE
+ | OPTION_MASK_ISA_AVX)))
+ sorry ("%s isn%'t supported in Intel MCU psABI",
+ TARGET_MMX_P (opts->x_ix86_isa_flags)
+ ? "MMX"
+ : TARGET_SSE_P (opts->x_ix86_isa_flags) ? "SSE" : "AVX");
+ }
+
if (!strcmp (opts->x_ix86_arch_string, "generic"))
error ("generic CPU can be used only for %stune=%s %s",
prefix, suffix, sw);
@@ -3904,7 +3922,16 @@ ix86_option_override_internal (bool main_args_p,
if (opts->x_flag_asynchronous_unwind_tables == 2)
opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER;
if (opts->x_flag_pcc_struct_return == 2)
- opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
+ {
+ /* Intel MCU psABI specifies that -freg-struct-return should
+ be on. Instead of setting DEFAULT_PCC_STRUCT_RETURN to 1,
+ we check -miamcu so that -freg-struct-return is always
+ turned on if -miamcu is used. */
+ if (TARGET_IAMCU_P (opts->x_target_flags))
+ opts->x_flag_pcc_struct_return = 0;
+ else
+ opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
+ }
}
ix86_tune_cost = processor_target_table[ix86_tune].cost;
@@ -3923,6 +3950,8 @@ ix86_option_override_internal (bool main_args_p,
{
if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
warning (0, "-mregparm is ignored in 64-bit mode");
+ else if (TARGET_IAMCU_P (opts->x_target_flags))
+ warning (0, "-mregparm is ignored for Intel MCU psABI");
if (opts->x_ix86_regparm > REGPARM_MAX)
{
error ("-mregparm=%d is not between 0 and %d",
@@ -3930,7 +3959,8 @@ ix86_option_override_internal (bool main_args_p,
opts->x_ix86_regparm = 0;
}
}
- if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
+ if (TARGET_IAMCU_P (opts->x_target_flags)
+ || TARGET_64BIT_P (opts->x_ix86_isa_flags))
opts->x_ix86_regparm = REGPARM_MAX;
/* Default align_* from the processor table. */
@@ -4334,8 +4364,9 @@ ix86_option_override_internal (bool main_args_p,
opts->x_recip_mask &= ~(RECIP_MASK_ALL & ~opts->x_recip_mask_explicit);
/* Default long double to 64-bit for 32-bit Bionic and to __float128
- for 64-bit Bionic. */
- if (TARGET_HAS_BIONIC
+ for 64-bit Bionic. Also default long double to 64-bit for Intel
+ MCU psABI. */
+ if ((TARGET_HAS_BIONIC || TARGET_IAMCU)
&& !(opts_set->x_target_flags
& (MASK_LONG_DOUBLE_64 | MASK_LONG_DOUBLE_128)))
opts->x_target_flags |= (TARGET_64BIT
@@ -7455,6 +7486,15 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
int res = 0;
bool error_p = NULL;
+ if (TARGET_IAMCU)
+ {
+ /* Intel MCU psABI passes scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (bytes <= 8)
+ goto pass_in_reg;
+ return res;
+ }
+
switch (mode)
{
default:
@@ -7469,6 +7509,7 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
case SImode:
case HImode:
case QImode:
+pass_in_reg:
cum->words += words;
cum->nregs -= words;
cum->regno += words;
@@ -7702,6 +7743,15 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
if (mode == VOIDmode)
return constm1_rtx;
+ if (TARGET_IAMCU)
+ {
+ /* Intel MCU psABI passes scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (bytes <= 8)
+ goto pass_in_reg;
+ return NULL_RTX;
+ }
+
switch (mode)
{
default:
@@ -7715,6 +7765,7 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode,
case SImode:
case HImode:
case QImode:
+pass_in_reg:
if (words <= cum->nregs)
{
int regno = cum->regno;
@@ -8561,11 +8612,16 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
}
else
{
+ size = int_size_in_bytes (type);
+
+ /* Intel MCU psABI returns scalars and aggregates no larger than 8
+ bytes in registers. */
+ if (TARGET_IAMCU)
+ return size > 8;
+
if (mode == BLKmode)
return true;
- size = int_size_in_bytes (type);
-
if (MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P (type) && size <= 8)
return false;
@@ -27334,6 +27390,34 @@ ix86_constant_alignment (tree exp, int align)
return align;
}
+/* Compute the alignment for a variable for Intel MCU psABI. TYPE is
+ the data type, and ALIGN is the alignment that the object would
+ ordinarily have. */
+
+static int
+iamcu_alignment (tree type, int align)
+{
+ enum machine_mode mode;
+
+ if (align < 32 || TYPE_USER_ALIGN (type))
+ return align;
+
+ /* Intel MCU psABI specifies scalar types > 4 bytes aligned to 4
+ bytes. */
+ mode = TYPE_MODE (strip_array_types (type));
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_INT:
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ case MODE_FLOAT:
+ case MODE_DECIMAL_FLOAT:
+ return 32;
+ default:
+ return align;
+ }
+}
+
/* Compute the alignment for a static variable.
TYPE is the data type, and ALIGN is the alignment that
the object would ordinarily have. The value of this function is used
@@ -27368,6 +27452,9 @@ ix86_data_alignment (tree type, int align, bool opt)
case ix86_align_data_type_cacheline: break;
}
+ if (TARGET_IAMCU)
+ align = iamcu_alignment (type, align);
+
if (opt
&& AGGREGATE_TYPE_P (type)
&& TYPE_SIZE (type)
@@ -27477,6 +27564,10 @@ ix86_local_alignment (tree exp, machine_mode mode,
return align;
}
+ /* Don't increase alignment for Intel MCU psABI. */
+ if (TARGET_IAMCU)
+ return align;
+
/* x86-64 ABI requires arrays greater than 16 bytes to be aligned
to 16byte boundary. Exact wording is:
@@ -43187,6 +43278,8 @@ x86_field_alignment (tree field, int computed)
if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
return computed;
+ if (TARGET_IAMCU)
+ return iamcu_alignment (type, computed);
mode = TYPE_MODE (strip_array_types (type));
if (mode == DFmode || mode == DCmode
|| GET_MODE_CLASS (mode) == MODE_INT
@@ -45555,21 +45648,144 @@ ix86_c_mode_for_suffix (char suffix)
/* Worker function for TARGET_MD_ASM_ADJUST.
- We do this in the new i386 backend to maintain source compatibility
+ We implement asm flag outputs, and maintain source compatibility
with the old cc0-based compiler. */
static rtx_insn *
-ix86_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
- vec<const char *> &/*constraints*/,
+ix86_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
+ vec<const char *> &constraints,
vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs)
{
- clobbers.safe_push (gen_rtx_REG (CCmode, FLAGS_REG));
clobbers.safe_push (gen_rtx_REG (CCFPmode, FPSR_REG));
-
- SET_HARD_REG_BIT (clobbered_regs, FLAGS_REG);
SET_HARD_REG_BIT (clobbered_regs, FPSR_REG);
- return NULL;
+ bool saw_asm_flag = false;
+
+ start_sequence ();
+ for (unsigned i = 0, n = outputs.length (); i < n; ++i)
+ {
+ const char *con = constraints[i];
+ if (strncmp (con, "=@cc", 4) != 0)
+ continue;
+ con += 4;
+ if (strchr (con, ',') != NULL)
+ {
+ error ("alternatives not allowed in asm flag output");
+ continue;
+ }
+
+ bool invert = false;
+ if (con[0] == 'n')
+ invert = true, con++;
+
+ machine_mode mode = CCmode;
+ rtx_code code = UNKNOWN;
+
+ switch (con[0])
+ {
+ case 'a':
+ if (con[1] == 0)
+ mode = CCAmode, code = EQ;
+ else if (con[1] == 'e' && con[2] == 0)
+ mode = CCCmode, code = EQ;
+ break;
+ case 'b':
+ if (con[1] == 0)
+ mode = CCCmode, code = EQ;
+ else if (con[1] == 'e' && con[2] == 0)
+ mode = CCAmode, code = NE;
+ break;
+ case 'c':
+ if (con[1] == 0)
+ mode = CCCmode, code = EQ;
+ break;
+ case 'e':
+ if (con[1] == 0)
+ mode = CCZmode, code = EQ;
+ break;
+ case 'g':
+ if (con[1] == 0)
+ mode = CCGCmode, code = GT;
+ else if (con[1] == 'e' && con[2] == 0)
+ mode = CCGCmode, code = GE;
+ break;
+ case 'l':
+ if (con[1] == 0)
+ mode = CCGCmode, code = LT;
+ else if (con[1] == 'e' && con[2] == 0)
+ mode = CCGCmode, code = LE;
+ break;
+ case 'o':
+ if (con[1] == 0)
+ mode = CCOmode, code = EQ;
+ break;
+ case 'p':
+ if (con[1] == 0)
+ mode = CCPmode, code = EQ;
+ break;
+ case 's':
+ if (con[1] == 0)
+ mode = CCSmode, code = EQ;
+ break;
+ case 'z':
+ if (con[1] == 0)
+ mode = CCZmode, code = EQ;
+ break;
+ }
+ if (code == UNKNOWN)
+ {
+ error ("unknown asm flag output %qs", constraints[i]);
+ continue;
+ }
+ if (invert)
+ code = reverse_condition (code);
+
+ rtx dest = outputs[i];
+ if (!saw_asm_flag)
+ {
+ /* This is the first asm flag output. Here we put the flags
+ register in as the real output and adjust the condition to
+ allow it. */
+ constraints[i] = "=Bf";
+ outputs[i] = gen_rtx_REG (CCmode, FLAGS_REG);
+ saw_asm_flag = true;
+ }
+ else
+ {
+ /* We don't need the flags register as output twice. */
+ constraints[i] = "=X";
+ outputs[i] = gen_rtx_SCRATCH (SImode);
+ }
+
+ rtx x = gen_rtx_REG (mode, FLAGS_REG);
+ x = gen_rtx_fmt_ee (code, QImode, x, const0_rtx);
+
+ machine_mode dest_mode = GET_MODE (dest);
+ if (!SCALAR_INT_MODE_P (dest_mode))
+ {
+ error ("invalid type for asm flag output");
+ continue;
+ }
+ if (dest_mode != QImode)
+ {
+ rtx destqi = gen_reg_rtx (QImode);
+ emit_insn (gen_rtx_SET (destqi, x));
+ x = gen_rtx_ZERO_EXTEND (dest_mode, destqi);
+ }
+ emit_insn (gen_rtx_SET (dest, x));
+ }
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+
+ if (saw_asm_flag)
+ return seq;
+ else
+ {
+ /* If we had no asm flag outputs, clobber the flags. */
+ clobbers.safe_push (gen_rtx_REG (CCmode, FLAGS_REG));
+ SET_HARD_REG_BIT (clobbered_regs, FLAGS_REG);
+ return NULL;
+ }
}
/* Implements target vector targetm.asm.encode_section_info. */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e0af36cec34..d710b3d2643 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -756,7 +756,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
/* It should be MIN_STACK_BOUNDARY. But we set it to 128 bits for
both 32bit and 64bit, to support codes that need 128 bit stack
alignment for SSE instructions, but can't realign the stack. */
-#define PREFERRED_STACK_BOUNDARY_DEFAULT 128
+#define PREFERRED_STACK_BOUNDARY_DEFAULT \
+ (TARGET_IAMCU ? MIN_STACK_BOUNDARY : 128)
/* 1 if -mstackrealign should be turned on by default. It will
generate an alternate prologue and epilogue that realigns the
@@ -803,7 +804,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
TARGET_ABSOLUTE_BIGGEST_ALIGNMENT. */
#define BIGGEST_ALIGNMENT \
- (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : 128))
+ (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : (TARGET_IAMCU ? 32 : 128)))
/* Maximum stack alignment. */
#define MAX_STACK_ALIGNMENT MAX_OFILE_ALIGNMENT
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 25935818ac9..ff7baa4b66f 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -10948,24 +10948,6 @@
;; Basic conditional jump instructions.
;; We ignore the overflow flag for signed branch instructions.
-(define_insn "*jcc_1_bnd"
- [(set (pc)
- (if_then_else (match_operator 1 "ix86_comparison_operator"
- [(reg FLAGS_REG) (const_int 0)])
- (label_ref (match_operand 0))
- (pc)))]
- "TARGET_MPX && ix86_bnd_prefixed_insn_p (insn)"
- "bnd %+j%C1\t%l0"
- [(set_attr "type" "ibr")
- (set_attr "modrm" "0")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -126))
- (lt (minus (match_dup 0) (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 7)))])
-
(define_insn "*jcc_1"
[(set (pc)
(if_then_else (match_operator 1 "ix86_comparison_operator"
@@ -10973,34 +10955,17 @@
(label_ref (match_operand 0))
(pc)))]
""
- "%+j%C1\t%l0"
+ "%!%+j%C1\t%l0"
[(set_attr "type" "ibr")
(set_attr "modrm" "0")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -126))
- (lt (minus (match_dup 0) (pc))
- (const_int 128)))
- (const_int 2)
- (const_int 6)))])
-
-(define_insn "*jcc_2_bnd"
- [(set (pc)
- (if_then_else (match_operator 1 "ix86_comparison_operator"
- [(reg FLAGS_REG) (const_int 0)])
- (pc)
- (label_ref (match_operand 0))))]
- "TARGET_MPX && ix86_bnd_prefixed_insn_p (insn)"
- "bnd %+j%c1\t%l0"
- [(set_attr "type" "ibr")
- (set_attr "modrm" "0")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -126))
- (lt (minus (match_dup 0) (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 7)))])
+ (set (attr "length_nobnd")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc))
+ (const_int -126))
+ (lt (minus (match_dup 0) (pc))
+ (const_int 128)))
+ (const_int 2)
+ (const_int 6)))])
(define_insn "*jcc_2"
[(set (pc)
@@ -11009,16 +10974,17 @@
(pc)
(label_ref (match_operand 0))))]
""
- "%+j%c1\t%l0"
+ "%!%+j%c1\t%l0"
[(set_attr "type" "ibr")
(set_attr "modrm" "0")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -126))
- (lt (minus (match_dup 0) (pc))
- (const_int 128)))
- (const_int 2)
- (const_int 6)))])
+ (set (attr "length_nobnd")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc))
+ (const_int -126))
+ (lt (minus (match_dup 0) (pc))
+ (const_int 128)))
+ (const_int 2)
+ (const_int 6)))])
;; In general it is not safe to assume too much about CCmode registers,
;; so simplify-rtx stops when it sees a second one. Under certain
@@ -11452,35 +11418,21 @@
;; Unconditional and other jump instructions
-(define_insn "jump_bnd"
- [(set (pc)
- (label_ref (match_operand 0)))]
- "TARGET_MPX && ix86_bnd_prefixed_insn_p (insn)"
- "bnd jmp\t%l0"
- [(set_attr "type" "ibr")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -126))
- (lt (minus (match_dup 0) (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 6)))
- (set_attr "modrm" "0")])
-
(define_insn "jump"
[(set (pc)
(label_ref (match_operand 0)))]
""
- "jmp\t%l0"
+ "%!jmp\t%l0"
[(set_attr "type" "ibr")
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -126))
- (lt (minus (match_dup 0) (pc))
- (const_int 128)))
- (const_int 2)
- (const_int 5)))
- (set_attr "modrm" "0")])
+ (set_attr "modrm" "0")
+ (set (attr "length_nobnd")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc))
+ (const_int -126))
+ (lt (minus (match_dup 0) (pc))
+ (const_int 128)))
+ (const_int 2)
+ (const_int 5)))])
(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "indirect_branch_operand"))]
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index dd46e26de39..042f3c1ab20 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -514,6 +514,10 @@ Clear all tune features
mdump-tune-features
Target RejectNegative Var(ix86_dump_tunes) Init(0)
+miamcu
+Target Report Mask(IAMCU)
+Generate code that conforms to Intel MCU psABI
+
mabi=
Target RejectNegative Joined Var(ix86_abi) Enum(calling_abi) Init(SYSV_ABI)
Generate code that conforms to the given ABI
diff --git a/gcc/config/i386/iamcu.h b/gcc/config/i386/iamcu.h
new file mode 100644
index 00000000000..a1c83f4dc13
--- /dev/null
+++ b/gcc/config/i386/iamcu.h
@@ -0,0 +1,42 @@
+/* Definitions of target machine for Intel MCU psABI.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Intel MCU has no 80387. Default to Intel MCU psABI. */
+#undef TARGET_SUBTARGET_DEFAULT
+#define TARGET_SUBTARGET_DEFAULT MASK_IAMCU
+
+#undef ASM_SPEC
+#define ASM_SPEC "--32 -march=iamcu"
+
+#undef LINK_SPEC
+#define LINK_SPEC "-m elf_iamcu"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC ""
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0.o%s"
+
+#undef LIB_SPEC
+#define LIB_SPEC "--start-group -lc -lgloss --end-group"
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 0e9c40bf9ed..832b05d46f6 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -1920,7 +1920,7 @@ nios2_delegitimize_address (rtx x)
case UNSPEC_LOAD_TLS_IE:
case UNSPEC_ADD_TLS_LE:
x = XVECEXP (XEXP (x, 0), 0, 0);
- gcc_assert (GET_CODE (x) == SYMBOL_REF);
+ gcc_assert (CONSTANT_P (x));
break;
}
}
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 43f197f17a1..3d6315a76b0 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -1,3 +1,4 @@
+
/* Target code for NVPTX.
Copyright (C) 2014-2015 Free Software Foundation, Inc.
Contributed by Bernd Schmidt <bernds@codesourcery.com>
@@ -1877,20 +1878,11 @@ get_replacement (struct reg_replace *r)
conversion copyin/copyout instructions. */
static void
-nvptx_reorg (void)
+nvptx_reorg_subreg (void)
{
struct reg_replace qiregs, hiregs, siregs, diregs;
rtx_insn *insn, *next;
- /* We are freeing block_for_insn in the toplev to keep compatibility
- with old MDEP_REORGS that are not CFG based. Recompute it now. */
- compute_bb_for_insn ();
-
- df_clear_flags (DF_LR_RUN_DCE);
- df_analyze ();
-
- thread_prologue_and_epilogue_insns ();
-
qiregs.n_allocated = 0;
hiregs.n_allocated = 0;
siregs.n_allocated = 0;
@@ -1966,14 +1958,44 @@ nvptx_reorg (void)
validate_change (insn, recog_data.operand_loc[i], new_reg, false);
}
}
+}
- int maxregs = max_reg_num ();
+/* PTX-specific reorganization
+ 1) mark now-unused registers, so function begin doesn't declare
+ unused registers.
+ 2) replace subregs with suitable sequences.
+*/
+
+static void
+nvptx_reorg (void)
+{
+ struct reg_replace qiregs, hiregs, siregs, diregs;
+ rtx_insn *insn, *next;
+
+ /* We are freeing block_for_insn in the toplev to keep compatibility
+ with old MDEP_REORGS that are not CFG based. Recompute it now. */
+ compute_bb_for_insn ();
+
+ thread_prologue_and_epilogue_insns ();
+
+ df_clear_flags (DF_LR_RUN_DCE);
+ df_set_flags (DF_NO_INSN_RESCAN | DF_NO_HARD_REGS);
+ df_analyze ();
regstat_init_n_sets_and_refs ();
- for (int i = LAST_VIRTUAL_REGISTER + 1; i < maxregs; i++)
+ int max_regs = max_reg_num ();
+
+ /* Mark unused regs as unused. */
+ for (int i = LAST_VIRTUAL_REGISTER + 1; i < max_regs; i++)
if (REG_N_SETS (i) == 0 && REG_N_REFS (i) == 0)
regno_reg_rtx[i] = const0_rtx;
+
+ /* Replace subregs. */
+ nvptx_reorg_subreg (max_regs);
+
regstat_free_n_sets_and_refs ();
+
+ df_finish_pass (true);
}
/* Handle a "kernel" attribute; arguments as in
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 35113c092c0..5c8d3068255 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -11344,6 +11344,8 @@ label:
LABEL_NUSES (operands[2])++;
})
+;; This may be replaced with casesi_worker_2 in sh_reorg for PIC.
+;; The insn length is set to 8 for that case.
(define_insn "casesi_worker_1"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(unspec:SI [(reg:SI R0_REG)
@@ -11375,7 +11377,9 @@ label:
gcc_unreachable ();
}
}
- [(set_attr "length" "4")])
+ [(set_attr_alternative "length"
+ [(if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))
+ (if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))])])
(define_insn "casesi_worker_2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
diff --git a/gcc/config/sparc/leon.md b/gcc/config/sparc/leon.md
index aca92fc7bf8..c579e394b58 100644
--- a/gcc/config/sparc/leon.md
+++ b/gcc/config/sparc/leon.md
@@ -24,12 +24,14 @@
(define_cpu_unit "leon_memory" "leon")
(define_insn_reservation "leon_load" 1
- (and (eq_attr "cpu" "leon") (eq_attr "type" "load,sload"))
+ (and (eq_attr "cpu" "leon,leon3,leon3v7")
+ (and (eq_attr "fix_ut699" "false") (eq_attr "type" "load,sload")))
"leon_memory")
;; Use a double reservation to work around the load pipeline hazard on UT699.
-(define_insn_reservation "leon3_load" 1
- (and (eq_attr "cpu" "leon3,leon3v7") (eq_attr "type" "load,sload"))
+(define_insn_reservation "ut699_load" 1
+ (and (eq_attr "cpu" "leon,leon3,leon3v7")
+ (and (eq_attr "fix_ut699" "true") (eq_attr "type" "load,sload")))
"leon_memory*2")
(define_insn_reservation "leon_store" 2
diff --git a/gcc/configure b/gcc/configure
index 3f3f5785d57..50d7037c37e 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -7317,7 +7317,7 @@ else
case $target in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
@@ -25048,7 +25048,7 @@ if test "${gcc_cv_as_ix86_filds+set}" = set; then :
else
gcc_cv_as_ix86_filds=no
if test x$gcc_cv_as != x; then
- $as_echo 'filds mem; fists mem' > conftest.s
+ $as_echo 'filds (%ebp); fists (%ebp)' > conftest.s
if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
@@ -25079,7 +25079,7 @@ if test "${gcc_cv_as_ix86_fildq+set}" = set; then :
else
gcc_cv_as_ix86_fildq=no
if test x$gcc_cv_as != x; then
- $as_echo 'fildq mem; fistpq mem' > conftest.s
+ $as_echo 'fildq (%ebp); fistpq (%ebp)' > conftest.s
if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 85f72d50dbf..88aecdbf3e1 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3885,13 +3885,13 @@ foo: nop
gcc_GAS_CHECK_FEATURE([filds and fists mnemonics],
gcc_cv_as_ix86_filds,,,
- [filds mem; fists mem],,
+ [filds (%ebp); fists (%ebp)],,
[AC_DEFINE(HAVE_AS_IX86_FILDS, 1,
[Define if your assembler uses filds and fists mnemonics.])])
gcc_GAS_CHECK_FEATURE([fildq and fistpq mnemonics],
gcc_cv_as_ix86_fildq,,,
- [fildq mem; fistpq mem],,
+ [fildq (%ebp); fistpq (%ebp)],,
[AC_DEFINE(HAVE_AS_IX86_FILDQ, 1,
[Define if your assembler uses fildq and fistq mnemonics.])])
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4a3b2d8a071..e3436418259 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,64 @@
+2015-07-01 Patrick Palka <ppalka@gcc.gnu.org>
+
+ PR c++/66686
+ * pt.c (coerce_template_template_parm) [PARM_DECL]: Don't
+ return 0 if tsubst returns a dependent type.
+
+2015-06-30 Jason Merrill <jason@redhat.com>
+
+ PR debug/66653
+ * decl2.c (is_late_template_attribute): True for tls_model.
+
+ PR debug/66653
+ * cp-tree.h (CP_DECL_THREAD_LOCAL_P): New.
+ (DECL_GNU_TLS_P): Use DECL_LANG_SPECIFIC field.
+ (SET_DECL_GNU_TLS_P): New.
+ * call.c (make_temporary_var_for_ref_to_temp): Use
+ CP_DECL_THREAD_LOCAL_P.
+ (set_up_extended_ref_temp): Likewise.
+ * decl.c (duplicate_decls, expand_static_init): Likewise.
+ (redeclaration_error_message, grokvardecl): Likewise.
+ (start_decl, register_dtor_fn, grokdeclarator): Likewise.
+ * decl2.c (get_guard, var_needs_tls_wrapper): Likewise.
+ (handle_tls_init): Likewise.
+ * pt.c (tsubst_decl, tsubst_copy_and_build): Likewise.
+ * semantics.c (finish_id_expression): Likewise.
+ (handle_omp_array_sections_1, finish_omp_clauses): Likewise.
+ (finish_omp_threadprivate): Likewise.
+ * tree.c (decl_storage_duration): Likewise.
+ * cp-gimplify.c (omp_var_to_track): Likewise.
+ (cp_genericize_r): Check that it matches DECL_THREAD_LOCAL_P.
+ * lex.c (retrofit_lang_decl): Return if DECL_LANG_SPECIFIC is
+ already set.
+
+2015-06-30 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement N4197 - Adding u8 character literals
+ * parser.c (cp_parser_primary_expression()): Treat CPP_UTF8CHAR
+ and CPP_UTF8CHAR_USERDEF tokens;
+ (cp_parser_parenthesized_expression_list()): Treat CPP_UTF8CHAR token.
+
+2015-06-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/65977
+ * decl.c (grokfndecl): Allow constexpr declarations of friend
+ template specializations.
+
+2015-06-29 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR fortran/66605
+ * decl.c (finish_function): Call do_warn_unused_parameter.
+
+2015-06-29 Marek Polacek <polacek@redhat.com>
+
+ PR c/66322
+ * decl.c (struct cp_switch): Add OUTSIDE_RANGE_P.
+ (push_switch): Set OUTSIDE_RANGE_P.
+ (pop_switch): Update c_do_switch_warnings call.
+ (finish_case_label): Update c_add_case_label call.
+ * semantics.c (finish_switch_cond): Don't warn about -Wswitch-bool
+ here.
+
2015-06-27 Marek Polacek <polacek@redhat.com>
* call.c: Use VECTOR_TYPE_P.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index b8469194f70..44346bf8f92 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -9556,13 +9556,14 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
/* Register the variable. */
if (VAR_P (decl)
- && (TREE_STATIC (decl) || DECL_THREAD_LOCAL_P (decl)))
+ && (TREE_STATIC (decl) || CP_DECL_THREAD_LOCAL_P (decl)))
{
/* Namespace-scope or local static; give it a mangled name. */
/* FIXME share comdat with decl? */
tree name;
TREE_STATIC (var) = TREE_STATIC (decl);
+ CP_DECL_THREAD_LOCAL_P (var) = CP_DECL_THREAD_LOCAL_P (decl);
set_decl_tls_model (var, DECL_TLS_MODEL (decl));
name = mangle_ref_init_variable (decl);
DECL_NAME (var) = name;
@@ -9683,7 +9684,7 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
rest_of_decl_compilation (var, /*toplev=*/1, at_eof);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
- if (DECL_THREAD_LOCAL_P (var))
+ if (CP_DECL_THREAD_LOCAL_P (var))
tls_aggregates = tree_cons (NULL_TREE, var,
tls_aggregates);
else
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 1a627db1db2..b95489e7816 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -831,7 +831,7 @@ omp_var_to_track (tree decl)
type = TREE_TYPE (type);
if (type == error_mark_node || !CLASS_TYPE_P (type))
return false;
- if (VAR_P (decl) && DECL_THREAD_LOCAL_P (decl))
+ if (VAR_P (decl) && CP_DECL_THREAD_LOCAL_P (decl))
return false;
if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
return false;
@@ -1157,6 +1157,12 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
*stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
*walk_subtrees = 0;
}
+ else if (TREE_CODE (stmt) == DECL_EXPR)
+ {
+ tree d = DECL_EXPR_DECL (stmt);
+ if (TREE_CODE (d) == VAR_DECL)
+ gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d));
+ }
else if (TREE_CODE (stmt) == OMP_PARALLEL || TREE_CODE (stmt) == OMP_TASK)
{
struct cp_genericize_omp_taskreg omp_ctx;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e8cc38f97e6..18cf87e893a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -51,7 +51,7 @@ c-common.h, not after.
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF, SCOPE_REF)
PAREN_STRING_LITERAL (in STRING_CST)
- DECL_GNU_TLS_P (in VAR_DECL)
+ CP_DECL_THREAD_LOCAL_P (in VAR_DECL)
KOENIG_LOOKUP_P (in CALL_EXPR)
STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
@@ -2017,7 +2017,7 @@ struct GTY(()) lang_decl_base {
unsigned repo_available_p : 1; /* var or fn */
unsigned threadprivate_or_deleted_p : 1; /* var or fn */
unsigned anticipated_p : 1; /* fn, type or template */
- unsigned friend_attr : 1; /* fn, type or template */
+ unsigned friend_or_tls : 1; /* var, fn, type or template */
unsigned template_conv_p : 1; /* var or template */
unsigned odr_used : 1; /* var or fn */
unsigned u2sel : 1;
@@ -2438,7 +2438,16 @@ struct GTY(()) lang_decl {
and should not be added to the list of members for this class. */
#define DECL_FRIEND_P(NODE) \
(DECL_LANG_SPECIFIC (TYPE_FUNCTION_OR_TEMPLATE_DECL_CHECK (NODE)) \
- ->u.base.friend_attr)
+ ->u.base.friend_or_tls)
+
+/* Nonzero if the thread-local variable was declared with __thread as
+ opposed to thread_local. */
+#define DECL_GNU_TLS_P(NODE) \
+ (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) \
+ && DECL_LANG_SPECIFIC (NODE)->u.base.friend_or_tls)
+#define SET_DECL_GNU_TLS_P(NODE) \
+ (retrofit_lang_decl (VAR_DECL_CHECK (NODE)), \
+ DECL_LANG_SPECIFIC (NODE)->u.base.friend_or_tls = true)
/* A TREE_LIST of the types which have befriended this FUNCTION_DECL. */
#define DECL_BEFRIENDING_CLASSES(NODE) \
@@ -2566,9 +2575,11 @@ struct GTY(()) lang_decl {
(DECL_NAME (NODE) \
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__PRETTY_FUNCTION__"))
-/* Nonzero if the thread-local variable was declared with __thread
- as opposed to thread_local. */
-#define DECL_GNU_TLS_P(NODE) \
+/* Nonzero if the variable was declared to be thread-local.
+ We need a special C++ version of this test because the middle-end
+ DECL_THREAD_LOCAL_P uses the symtab, so we can't use it for
+ templates. */
+#define CP_DECL_THREAD_LOCAL_P(NODE) \
(TREE_LANG_FLAG_0 (VAR_DECL_CHECK (NODE)))
/* The _TYPE context in which this _DECL appears. This field holds the
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0683f26b7a0..9fabde7881b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2523,8 +2523,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
}
if (VAR_P (newdecl)
- && DECL_THREAD_LOCAL_P (newdecl))
- set_decl_tls_model (olddecl, DECL_TLS_MODEL (newdecl));
+ && CP_DECL_THREAD_LOCAL_P (newdecl))
+ {
+ CP_DECL_THREAD_LOCAL_P (olddecl) = true;
+ if (!processing_template_decl)
+ set_decl_tls_model (olddecl, DECL_TLS_MODEL (newdecl));
+ }
}
DECL_UID (olddecl) = olddecl_uid;
@@ -2702,14 +2706,14 @@ redeclaration_error_message (tree newdecl, tree olddecl)
return NULL;
}
else if (VAR_P (newdecl)
- && DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)
+ && CP_DECL_THREAD_LOCAL_P (newdecl) != CP_DECL_THREAD_LOCAL_P (olddecl)
&& (! DECL_LANG_SPECIFIC (olddecl)
|| ! CP_DECL_THREADPRIVATE_P (olddecl)
- || DECL_THREAD_LOCAL_P (newdecl)))
+ || CP_DECL_THREAD_LOCAL_P (newdecl)))
{
/* Only variables can be thread-local, and all declarations must
agree on this property. */
- if (DECL_THREAD_LOCAL_P (newdecl))
+ if (CP_DECL_THREAD_LOCAL_P (newdecl))
return G_("thread-local declaration of %q#D follows "
"non-thread-local declaration");
else
@@ -3208,6 +3212,9 @@ struct cp_switch
label. We need a tree, rather than simply a hash table, because
of the GNU case range extension. */
splay_tree cases;
+ /* Remember whether there was a case value that is outside the
+ range of the original type of the controlling expression. */
+ bool outside_range_p;
};
/* A stack of the currently active switch statements. The innermost
@@ -3229,6 +3236,7 @@ push_switch (tree switch_stmt)
p->next = switch_stack;
p->switch_stmt = switch_stmt;
p->cases = splay_tree_new (case_compare, NULL, NULL);
+ p->outside_range_p = false;
switch_stack = p;
}
@@ -3240,10 +3248,14 @@ pop_switch (void)
/* Emit warnings as needed. */
switch_location = EXPR_LOC_OR_LOC (cs->switch_stmt, input_location);
+ const bool bool_cond_p
+ = (SWITCH_STMT_TYPE (cs->switch_stmt)
+ && TREE_CODE (SWITCH_STMT_TYPE (cs->switch_stmt)) == BOOLEAN_TYPE);
if (!processing_template_decl)
c_do_switch_warnings (cs->cases, switch_location,
SWITCH_STMT_TYPE (cs->switch_stmt),
- SWITCH_STMT_COND (cs->switch_stmt));
+ SWITCH_STMT_COND (cs->switch_stmt),
+ bool_cond_p, cs->outside_range_p);
splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
@@ -3308,7 +3320,8 @@ finish_case_label (location_t loc, tree low_value, tree high_value)
high_value = case_conversion (type, high_value);
r = c_add_case_label (loc, switch_stack->cases, cond, type,
- low_value, high_value);
+ low_value, high_value,
+ &switch_stack->outside_range_p);
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
@@ -4850,7 +4863,7 @@ start_decl (const cp_declarator *declarator,
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
{
bool ok = false;
- if (DECL_THREAD_LOCAL_P (decl))
+ if (CP_DECL_THREAD_LOCAL_P (decl))
error ("%qD declared %<thread_local%> in %<constexpr%> function",
decl);
else if (TREE_STATIC (decl))
@@ -7047,7 +7060,7 @@ register_dtor_fn (tree decl)
function to do the cleanup. */
dso_parm = (flag_use_cxa_atexit
&& !targetm.cxx.use_atexit_for_cxa_atexit ());
- ob_parm = (DECL_THREAD_LOCAL_P (decl) || dso_parm);
+ ob_parm = (CP_DECL_THREAD_LOCAL_P (decl) || dso_parm);
use_dtor = ob_parm && CLASS_TYPE_P (type);
if (use_dtor)
{
@@ -7090,7 +7103,7 @@ register_dtor_fn (tree decl)
mark_used (cleanup);
cleanup = build_address (cleanup);
- if (DECL_THREAD_LOCAL_P (decl))
+ if (CP_DECL_THREAD_LOCAL_P (decl))
atex_node = get_thread_atexit_node ();
else
atex_node = get_atexit_node ();
@@ -7130,7 +7143,7 @@ register_dtor_fn (tree decl)
if (ob_parm)
{
- if (!DECL_THREAD_LOCAL_P (decl)
+ if (!CP_DECL_THREAD_LOCAL_P (decl)
&& targetm.cxx.use_aeabi_atexit ())
{
arg1 = cleanup;
@@ -7170,7 +7183,7 @@ expand_static_init (tree decl, tree init)
return;
}
- if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
+ if (CP_DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
&& !DECL_FUNCTION_SCOPE_P (decl))
{
if (init)
@@ -7199,7 +7212,7 @@ expand_static_init (tree decl, tree init)
tree flag, begin;
/* We don't need thread-safety code for thread-local vars. */
bool thread_guard = (flag_threadsafe_statics
- && !DECL_THREAD_LOCAL_P (decl));
+ && !CP_DECL_THREAD_LOCAL_P (decl));
/* Emit code to perform this initialization but once. This code
looks like:
@@ -7312,7 +7325,7 @@ expand_static_init (tree decl, tree init)
finish_then_clause (if_stmt);
finish_if_stmt (if_stmt);
}
- else if (DECL_THREAD_LOCAL_P (decl))
+ else if (CP_DECL_THREAD_LOCAL_P (decl))
tls_aggregates = tree_cons (init, decl, tls_aggregates);
else
static_aggregates = tree_cons (init, decl, static_aggregates);
@@ -7729,15 +7742,12 @@ grokfndecl (tree ctype,
}
if (inlinep & 1)
- error ("%<inline%> is not allowed in declaration of friend "
- "template specialization %qD",
- decl);
- if (inlinep & 2)
- error ("%<constexpr%> is not allowed in declaration of friend "
- "template specialization %qD",
- decl);
- if (inlinep)
- return NULL_TREE;
+ {
+ error ("%<inline%> is not allowed in declaration of friend "
+ "template specialization %qD",
+ decl);
+ return NULL_TREE;
+ }
}
}
@@ -8176,9 +8186,13 @@ grokvardecl (tree type,
if (decl_spec_seq_has_spec_p (declspecs, ds_thread))
{
if (DECL_EXTERNAL (decl) || TREE_STATIC (decl))
- set_decl_tls_model (decl, decl_default_tls_model (decl));
+ {
+ CP_DECL_THREAD_LOCAL_P (decl) = true;
+ if (!processing_template_decl)
+ set_decl_tls_model (decl, decl_default_tls_model (decl));
+ }
if (declspecs->gnu_thread_keyword_p)
- DECL_GNU_TLS_P (decl) = true;
+ SET_DECL_GNU_TLS_P (decl);
}
/* If the type of the decl has no linkage, make sure that we'll
@@ -10851,9 +10865,11 @@ grokdeclarator (const cp_declarator *declarator,
if (thread_p)
{
- set_decl_tls_model (decl, decl_default_tls_model (decl));
+ CP_DECL_THREAD_LOCAL_P (decl) = true;
+ if (!processing_template_decl)
+ set_decl_tls_model (decl, decl_default_tls_model (decl));
if (declspecs->gnu_thread_keyword_p)
- DECL_GNU_TLS_P (decl) = true;
+ SET_DECL_GNU_TLS_P (decl);
}
if (constexpr_p && !initialized)
@@ -14314,6 +14330,12 @@ finish_function (int flags)
function. */
maybe_warn_unused_local_typedefs ();
+ /* Possibly warn about unused parameters. */
+ if (warn_unused_parameter
+ && !processing_template_decl
+ && !DECL_CLONED_FUNCTION_P (fndecl))
+ do_warn_unused_parameter (fndecl);
+
/* Genericize before inlining. */
if (!processing_template_decl)
{
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a7a6efb25f2..0332aa239a4 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1164,6 +1164,10 @@ is_late_template_attribute (tree attr, tree decl)
if (is_attribute_p ("unused", name))
return false;
+ /* Attribute tls_model wants to modify the symtab. */
+ if (is_attribute_p ("tls_model", name))
+ return true;
+
/* #pragma omp declare simd attribute needs to be always deferred. */
if (flag_openmp
&& is_attribute_p ("omp declare simd", name))
@@ -3005,6 +3009,7 @@ get_guard (tree decl)
TREE_STATIC (guard) = TREE_STATIC (decl);
DECL_COMMON (guard) = DECL_COMMON (decl);
DECL_COMDAT (guard) = DECL_COMDAT (decl);
+ CP_DECL_THREAD_LOCAL_P (guard) = CP_DECL_THREAD_LOCAL_P (decl);
set_decl_tls_model (guard, DECL_TLS_MODEL (decl));
if (DECL_ONE_ONLY (decl))
make_decl_one_only (guard, cxx_comdat_group (guard));
@@ -3143,7 +3148,7 @@ static bool
var_needs_tls_wrapper (tree var)
{
return (!error_operand_p (var)
- && DECL_THREAD_LOCAL_P (var)
+ && CP_DECL_THREAD_LOCAL_P (var)
&& !DECL_GNU_TLS_P (var)
&& !DECL_FUNCTION_SCOPE_P (var)
&& !var_defined_without_dynamic_init (var));
@@ -4278,6 +4283,7 @@ handle_tls_init (void)
DECL_ARTIFICIAL (guard) = true;
DECL_IGNORED_P (guard) = true;
TREE_USED (guard) = true;
+ CP_DECL_THREAD_LOCAL_P (guard) = true;
set_decl_tls_model (guard, decl_default_tls_model (guard));
pushdecl_top_level_and_finish (guard, NULL_TREE);
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 9bbdba5a7ec..915fbddff02 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -553,6 +553,9 @@ retrofit_lang_decl (tree t)
size_t size;
int sel;
+ if (DECL_LANG_SPECIFIC (t))
+ return;
+
if (TREE_CODE (t) == FUNCTION_DECL)
sel = 1, size = sizeof (struct lang_decl_fn);
else if (TREE_CODE (t) == NAMESPACE_DECL)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index acf147c0e5c..bb3d636eee1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4284,6 +4284,7 @@ cp_parser_primary_expression (cp_parser *parser,
case CPP_CHAR16:
case CPP_CHAR32:
case CPP_WCHAR:
+ case CPP_UTF8CHAR:
case CPP_NUMBER:
case CPP_PREPARSED_EXPR:
if (TREE_CODE (token->u.value) == USERDEF_LITERAL)
@@ -4345,6 +4346,7 @@ cp_parser_primary_expression (cp_parser *parser,
case CPP_CHAR16_USERDEF:
case CPP_CHAR32_USERDEF:
case CPP_WCHAR_USERDEF:
+ case CPP_UTF8CHAR_USERDEF:
return cp_parser_userdef_char_literal (parser);
case CPP_STRING:
@@ -6887,6 +6889,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
case CPP_WCHAR:
case CPP_CHAR16:
case CPP_CHAR32:
+ case CPP_UTF8CHAR:
/* If a parameter is literal zero alone, remember it
for -Wmemset-transposed-args warning. */
if (integer_zerop (tok->u.value)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 874f29f02c6..38d2e3a24e3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6363,11 +6363,13 @@ coerce_template_template_parm (tree parm,
D<int, C> d;
i.e. the parameter list of TT depends on earlier parameters. */
- if (!uses_template_parms (TREE_TYPE (arg))
- && !same_type_p
- (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
- TREE_TYPE (arg)))
- return 0;
+ if (!uses_template_parms (TREE_TYPE (arg)))
+ {
+ tree t = tsubst (TREE_TYPE (parm), outer_args, complain, in_decl);
+ if (!uses_template_parms (t)
+ && !same_type_p (t, TREE_TYPE (arg)))
+ return 0;
+ }
if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg))
&& !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
@@ -11467,8 +11469,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
}
SET_DECL_VALUE_EXPR (r, ve);
}
- if (TREE_STATIC (r) || DECL_EXTERNAL (r))
- set_decl_tls_model (r, decl_tls_model (t));
+ if (CP_DECL_THREAD_LOCAL_P (r)
+ && !processing_template_decl)
+ set_decl_tls_model (r, decl_default_tls_model (r));
}
else if (DECL_SELF_REFERENCE_P (t))
SET_DECL_SELF_REFERENCE_P (r);
@@ -15696,7 +15699,7 @@ tsubst_copy_and_build (tree t,
&& !processing_template_decl
&& !cp_unevaluated_operand
&& (TREE_STATIC (r) || DECL_EXTERNAL (r))
- && DECL_THREAD_LOCAL_P (r))
+ && CP_DECL_THREAD_LOCAL_P (r))
{
if (tree wrap = get_tls_wrapper_fn (r))
/* Replace an evaluated use of the thread_local variable with
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 4b8ce3b35ce..8de2522a6d4 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1156,11 +1156,6 @@ finish_switch_cond (tree cond, tree switch_stmt)
orig_type = TREE_TYPE (cond);
if (cond != error_mark_node)
{
- /* Warn if the condition has boolean value. */
- if (TREE_CODE (orig_type) == BOOLEAN_TYPE)
- warning_at (input_location, OPT_Wswitch_bool,
- "switch condition has type bool");
-
/* [stmt.switch]
Integral promotions are performed. */
@@ -3558,7 +3553,7 @@ finish_id_expression (tree id_expression,
&& !cp_unevaluated_operand
&& !processing_template_decl
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
- && DECL_THREAD_LOCAL_P (decl)
+ && CP_DECL_THREAD_LOCAL_P (decl)
&& (wrap = get_tls_wrapper_fn (decl)))
{
/* Replace an evaluated use of the thread_local variable with
@@ -4296,7 +4291,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
return error_mark_node;
}
else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
- && VAR_P (t) && DECL_THREAD_LOCAL_P (t))
+ && VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qD is threadprivate variable in %qs clause", t,
@@ -5789,7 +5784,7 @@ finish_omp_clauses (tree clauses)
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
- else if (VAR_P (t) && DECL_THREAD_LOCAL_P (t))
+ else if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
{
error ("%qD is threadprivate variable in %qs clause", t,
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
@@ -5959,7 +5954,7 @@ finish_omp_clauses (tree clauses)
break;
case OMP_CLAUSE_COPYIN:
- if (!VAR_P (t) || !DECL_THREAD_LOCAL_P (t))
+ if (!VAR_P (t) || !CP_DECL_THREAD_LOCAL_P (t))
{
error ("%qE must be %<threadprivate%> for %<copyin%>", t);
remove = true;
@@ -5987,7 +5982,7 @@ finish_omp_clauses (tree clauses)
{
const char *share_name = NULL;
- if (VAR_P (t) && DECL_THREAD_LOCAL_P (t))
+ if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
share_name = "threadprivate";
else switch (cxx_omp_predetermined_sharing (t))
{
@@ -6090,8 +6085,9 @@ finish_omp_threadprivate (tree vars)
DECL_LANG_SPECIFIC (v)->u.base.u2sel = 1;
}
- if (! DECL_THREAD_LOCAL_P (v))
+ if (! CP_DECL_THREAD_LOCAL_P (v))
{
+ CP_DECL_THREAD_LOCAL_P (v) = true;
set_decl_tls_model (v, decl_default_tls_model (v));
/* If rtl has been already set for this var, call
make_decl_rtl once again, so that encode_section_info
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index f1f5e533c7a..0d1112c33d0 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4036,7 +4036,7 @@ decl_storage_duration (tree decl)
if (!TREE_STATIC (decl)
&& !DECL_EXTERNAL (decl))
return dk_auto;
- if (DECL_THREAD_LOCAL_P (decl))
+ if (CP_DECL_THREAD_LOCAL_P (decl))
return dk_thread;
return dk_static;
}
diff --git a/gcc/cse.c b/gcc/cse.c
index 100c9c83e76..e01240cd2e6 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -5483,7 +5483,8 @@ cse_insn (rtx_insn *insn)
rtx_jump_insn *new_rtx;
rtx note;
- new_rtx = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn);
+ rtx_insn *seq = targetm.gen_jump (XEXP (src, 0));
+ new_rtx = emit_jump_insn_before (seq, insn);
JUMP_LABEL (new_rtx) = XEXP (src, 0);
LABEL_NUSES (XEXP (src, 0))++;
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 5534e42d8a0..ea10eb915bc 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -1426,66 +1426,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_VTABLE_USES_DESCRIPTORS 0
#endif
-#ifndef HAVE_epilogue
-#define HAVE_epilogue 0
-static inline rtx
-gen_epilogue ()
-{
- gcc_unreachable ();
- return NULL;
-}
-#endif
-
-#ifndef HAVE_mem_thread_fence
-#define HAVE_mem_thread_fence 0
-static inline rtx
-gen_mem_thread_fence (rtx)
-{
- gcc_unreachable ();
- return NULL;
-}
-#endif
-
-#ifndef HAVE_memory_barrier
-#define HAVE_memory_barrier 0
-static inline rtx
-gen_memory_barrier ()
-{
- gcc_unreachable ();
- return NULL;
-}
-#endif
-
-#ifndef HAVE_mem_signal_fence
-#define HAVE_mem_signal_fence 0
-static inline rtx
-gen_mem_signal_fence (rtx)
-{
- gcc_unreachable ();
- return NULL;
-}
-#endif
-
-#ifndef HAVE_load_multiple
-#define HAVE_load_multiple 0
-static inline rtx
-gen_load_multiple (rtx, rtx, rtx)
-{
- gcc_unreachable ();
- return NULL;
-}
-#endif
-
-#ifndef HAVE_store_multiple
-#define HAVE_store_multiple 0
-static inline rtx
-gen_store_multiple (rtx, rtx, rtx)
-{
- gcc_unreachable ();
- return NULL;
-}
-#endif
-
#ifndef HAVE_tablejump
#define HAVE_tablejump 0
static inline rtx
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 4e53f884443..22942407f26 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -52,13 +52,6 @@ along with GCC; see the file COPYING3. If not see
typedef struct df_mw_hardreg *df_mw_hardreg_ptr;
-#ifndef HAVE_prologue
-#define HAVE_prologue 0
-#endif
-#ifndef HAVE_sibcall_epilogue
-#define HAVE_sibcall_epilogue 0
-#endif
-
/* The set of hard registers in eliminables[i].from. */
static HARD_REG_SET elim_reg_set;
@@ -3523,7 +3516,7 @@ df_get_entry_block_def_set (bitmap entry_block_defs)
/* Once the prologue has been generated, all of these registers
should just show up in the first regular block. */
- if (HAVE_prologue && epilogue_completed)
+ if (targetm.have_prologue () && epilogue_completed)
{
/* Defs for the callee saved registers are inserted so that the
pushes have some defining location. */
@@ -3701,7 +3694,7 @@ df_get_exit_block_use_set (bitmap exit_block_uses)
if (global_regs[i] || EPILOGUE_USES (i))
bitmap_set_bit (exit_block_uses, i);
- if (HAVE_epilogue && epilogue_completed)
+ if (targetm.have_epilogue () && epilogue_completed)
{
/* Mark all call-saved registers that we actually used. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -3721,7 +3714,7 @@ df_get_exit_block_use_set (bitmap exit_block_uses)
}
#ifdef EH_RETURN_STACKADJ_RTX
- if ((!HAVE_epilogue || ! epilogue_completed)
+ if ((!targetm.have_epilogue () || ! epilogue_completed)
&& crtl->calls_eh_return)
{
rtx tmp = EH_RETURN_STACKADJ_RTX;
@@ -3731,7 +3724,7 @@ df_get_exit_block_use_set (bitmap exit_block_uses)
#endif
#ifdef EH_RETURN_HANDLER_RTX
- if ((!HAVE_epilogue || ! epilogue_completed)
+ if ((!targetm.have_epilogue () || ! epilogue_completed)
&& crtl->calls_eh_return)
{
rtx tmp = EH_RETURN_HANDLER_RTX;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 8258000510e..bb858a84f96 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7683,6 +7683,84 @@ pointed to by @code{e}
in a register, you can enable it to choose the best location
for @code{d} by specifying both constraints.
+@anchor{FlagOutputOperands}
+@subsection Flag Output Operands
+@cindex @code{asm} flag output operands
+
+Some targets have a special register that holds the ``flags'' for the
+result of an operation or comparison. Normally, the contents of that
+register are either unmodifed by the asm, or the asm is considered to
+clobber the contents.
+
+On some targets, a special form of output operand exists by which
+conditions in the flags register may be outputs of the asm. The set of
+conditions supported are target specific, but the general rule is that
+the output variable must be a scalar integer, and the value will be boolean.
+When supported, the target will define the preprocessor symbol
+@code{__GCC_ASM_FLAG_OUTPUTS__}.
+
+Because of the special nature of the flag output operands, the constraint
+may not include alternatives.
+
+Most often, the target has only one flags register, and thus is an implied
+operand of many instructions. In this case, the operand should not be
+referenced within the assembler template via @code{%0} etc, as there's
+no corresponding text in the assembly language.
+
+@table @asis
+@item x86 family
+The flag output constraints for the x86 family are of the form
+@samp{=@@cc@var{cond}} where @var{cond} is one of the standard
+conditions defined in the ISA manual for @code{j@var{cc}} or
+@code{set@var{cc}}.
+
+@table @code
+@item a
+``above'' or unsigned greater than
+@item ae
+``above or equal'' or unsigned greater than or equal
+@item b
+``below'' or unsigned less than
+@item be
+``below or equal'' or unsigned less than or equal
+@item c
+carry flag set
+@item e
+@itemx z
+``equal'' or zero flag set
+@item g
+signed greater than
+@item ge
+signed greater than or equal
+@item l
+signed less than
+@item le
+signed less than or equal
+@item o
+overflow flag set
+@item p
+parity flag set
+@item s
+sign flag set
+@item na
+@itemx nae
+@itemx nb
+@itemx nbe
+@itemx nc
+@itemx ne
+@itemx ng
+@itemx nge
+@itemx nl
+@itemx nle
+@itemx no
+@itemx np
+@itemx ns
+@itemx nz
+``not'' @var{flag}, or inverted versions of those above
+@end table
+
+@end table
+
@anchor{InputOperands}
@subsubsection Input Operands
@cindex @code{asm} input operands
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 844d7edaecf..0413106deb0 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1096,7 +1096,7 @@ See RS/6000 and PowerPC Options.
-mpc32 -mpc64 -mpc80 -mstackrealign @gol
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol
-mcmodel=@var{code-model} -mabi=@var{name} -maddress-mode=@var{mode} @gol
--m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol
+-m32 -m64 -mx32 -m16 -miamcu -mlarge-data-threshold=@var{num} @gol
-msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
-mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
-malign-data=@var{type} -mstack-protector-guard=@var{guard}}
@@ -4012,7 +4012,8 @@ warning about an omitted enumeration code even if there is a
@item -Wswitch-bool
@opindex Wswitch-bool
@opindex Wno-switch-bool
-Warn whenever a @code{switch} statement has an index of boolean type.
+Warn whenever a @code{switch} statement has an index of boolean type
+and the case values are outside the range of a boolean type.
It is possible to suppress this warning by casting the controlling
expression to a type other than @code{bool}. For example:
@smallexample
@@ -12429,24 +12430,26 @@ corresponding flag to the linker.
@opindex march
Specify the name of the target architecture, optionally suffixed by one or
more feature modifiers. This option has the form
-@option{-march=@var{arch}@r{@{}+@r{[}no@r{]}@var{feature}@r{@}*}}, where the
-permissible values for @var{arch} are @samp{armv8-a} or @samp{armv8.1-a}.
-The permissible values for @var{feature} are documented in the sub-section
-below. Additionally on native AArch64 GNU/Linux systems the value
+@option{-march=@var{arch}@r{@{}+@r{[}no@r{]}@var{feature}@r{@}*}}.
+
+The permissible values for @var{arch} are @samp{armv8-a} or
+@samp{armv8.1-a}.
+
+For the permissible values for @var{feature}, see the sub-section on
+@ref{aarch64-feature-modifiers,,@option{-march} and @option{-mcpu}
+Feature Modifiers}. Where conflicting feature modifiers are
+specified, the right-most feature is used.
+
+Additionally on native AArch64 GNU/Linux systems the value
@samp{native} is available. This option causes the compiler to pick the
architecture of the host system. If the compiler is unable to recognize the
architecture of the host system this option has no effect.
-Where conflicting feature modifiers are specified, the right-most feature is
-used.
-
-GCC uses this name to determine what kind of instructions it can emit when
-generating assembly code.
-
-Where @option{-march} is specified without either of @option{-mtune}
-or @option{-mcpu} also being specified, the code is tuned to perform
-well across a range of target processors implementing the target
-architecture.
+GCC uses @var{name} to determine what kind of instructions it can emit
+when generating assembly code. If @option{-march} is specified
+without either of @option{-mtune} or @option{-mcpu} also being
+specified, the code is tuned to perform well across a range of target
+processors implementing the target architecture.
@item -mtune=@var{name}
@opindex mtune
@@ -12459,12 +12462,11 @@ Additionally, this option can specify that GCC should tune the performance
of the code for a big.LITTLE system. Permissible values for this
option are: @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53}.
-Additionally on native AArch64 GNU/Linux systems the value @samp{native}
-is available.
-This option causes the compiler to pick the architecture of and tune the
-performance of the code for the processor of the host system.
-If the compiler is unable to recognize the processor of the host system
-this option has no effect.
+Additionally on native AArch64 GNU/Linux systems the value
+@samp{native} is available. This option causes the compiler to pick
+the architecture of and tune the performance of the code for the
+processor of the host system. If the compiler is unable to recognize
+the processor of the host system this option has no effect.
Where none of @option{-mtune=}, @option{-mcpu=} or @option{-march=}
are specified, the code is tuned to perform well across a range
@@ -12474,23 +12476,23 @@ This option cannot be suffixed by feature modifiers.
@item -mcpu=@var{name}
@opindex mcpu
-Specify the name of the target processor, optionally suffixed by one or more
-feature modifiers. This option has the form
-@option{-mcpu=@var{cpu}@r{@{}+@r{[}no@r{]}@var{feature}@r{@}*}}, where the
-permissible values for @var{cpu} are the same as those available for
-@option{-mtune}. Additionally on native AArch64 GNU/Linux systems the
-value @samp{native} is available.
-This option causes the compiler to tune the performance of the code for the
-processor of the host system. If the compiler is unable to recognize the
-processor of the host system this option has no effect.
-
-The permissible values for @var{feature} are documented in the sub-section
-below.
-
-Where conflicting feature modifiers are specified, the right-most feature is
-used.
+Specify the name of the target processor, optionally suffixed by one
+or more feature modifiers. This option has the form
+@option{-mcpu=@var{cpu}@r{@{}+@r{[}no@r{]}@var{feature}@r{@}*}}, where
+the permissible values for @var{cpu} are the same as those available
+for @option{-mtune}. The permissible values for @var{feature} are
+documented in the sub-section on
+@ref{aarch64-feature-modifiers,,@option{-march} and @option{-mcpu}
+Feature Modifiers}. Where conflicting feature modifiers are
+specified, the right-most feature is used.
+
+Additionally on native AArch64 GNU/Linux systems the value
+@samp{native} is available. This option causes the compiler to tune
+the performance of the code for the processor of the host system. If
+the compiler is unable to recognize the processor of the host system
+this option has no effect.
-GCC uses this name to determine what kind of instructions it can emit when
+GCC uses @var{name} to determine what kind of instructions it can emit when
generating assembly code (as if by @option{-march}) and to determine
the target processor for which to tune for performance (as if
by @option{-mtune}). Where this option is used in conjunction
@@ -12499,6 +12501,7 @@ over the appropriate part of this option.
@end table
@subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
+@anchor{aarch64-feature-modifiers}
@cindex @option{-march} feature modifiers
@cindex @option{-mcpu} feature modifiers
Feature modifiers used with @option{-march} and @option{-mcpu} can be any of
@@ -12524,7 +12527,8 @@ Enable Privileged Access Never support.
@item lor
Enable Limited Ordering Regions support.
@item rdma
-Enable ARMv8.1 Advanced SIMD instructions.
+Enable ARMv8.1 Advanced SIMD instructions. This implies Advanced SIMD
+is enabled.
@item -moverride=@var{string}
@opindex master
@@ -23285,10 +23289,12 @@ on x86-64 processors in 64-bit environments.
@itemx -m64
@itemx -mx32
@itemx -m16
+@itemx -miamcu
@opindex m32
@opindex m64
@opindex mx32
@opindex m16
+@opindex miamcu
Generate code for a 16-bit, 32-bit or 64-bit environment.
The @option{-m32} option sets @code{int}, @code{long}, and pointer types
to 32 bits, and
@@ -23307,6 +23313,9 @@ The @option{-m16} option is the same as @option{-m32}, except for that
it outputs the @code{.code16gcc} assembly directive at the beginning of
the assembly output so that the binary can run in 16-bit mode.
+The @option{-miamcu} option generates code which conforms to Intel MCU
+psABI. It requires the @option{-m32} option to be turned on.
+
@item -mno-red-zone
@opindex mno-red-zone
Do not use a so-called ``red zone'' for x86-64 code. The red zone is mandated
diff --git a/gcc/dojump.c b/gcc/dojump.c
index b062a569cf5..15b1ebf93cb 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "predict.h"
#include "basic-block.h"
#include "tm_p.h"
+#include "target.h"
static bool prefer_and_bit_test (machine_mode, int);
static void do_jump_by_parts_greater (tree, tree, int,
@@ -1204,13 +1205,12 @@ do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
unsignedp = TYPE_UNSIGNED (type);
code = unsignedp ? unsigned_code : signed_code;
-#ifdef HAVE_canonicalize_funcptr_for_compare
/* If function pointers need to be "canonicalized" before they can
be reliably compared, then canonicalize them.
Only do this if *both* sides of the comparison are function pointers.
If one side isn't, we want a noncanonicalized comparison. See PR
middle-end/17564. */
- if (HAVE_canonicalize_funcptr_for_compare
+ if (targetm.have_canonicalize_funcptr_for_compare ()
&& TREE_CODE (TREE_TYPE (treeop0)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (treeop0)))
== FUNCTION_TYPE
@@ -1221,13 +1221,12 @@ do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
rtx new_op0 = gen_reg_rtx (mode);
rtx new_op1 = gen_reg_rtx (mode);
- emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
+ emit_insn (targetm.gen_canonicalize_funcptr_for_compare (new_op0, op0));
op0 = new_op0;
- emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
+ emit_insn (targetm.gen_canonicalize_funcptr_for_compare (new_op1, op1));
op1 = new_op1;
}
-#endif
do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
((mode == BLKmode)
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index e7117fffcc1..b567b23f938 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -3476,11 +3476,10 @@ public:
bool
pass_dwarf2_frame::gate (function *)
{
-#ifndef HAVE_prologue
/* Targets which still implement the prologue in assembler text
cannot use the generic dwarf2 unwinding. */
- return false;
-#endif
+ if (!targetm.have_prologue ())
+ return false;
/* ??? What to do for UI_TARGET unwinding? They might be able to benefit
from the optimized shrink-wrapping annotations that we will compute.
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 3f7490899cb..69c48a6b8b4 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -4539,11 +4539,11 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
quotient, 0, OPTAB_LIB_WIDEN);
if (tem != quotient)
emit_move_insn (quotient, tem);
- emit_jump_insn (gen_jump (label5));
+ emit_jump_insn (targetm.gen_jump (label5));
emit_barrier ();
emit_label (label1);
expand_inc (adjusted_op0, const1_rtx);
- emit_jump_insn (gen_jump (label4));
+ emit_jump_insn (targetm.gen_jump (label4));
emit_barrier ();
emit_label (label2);
do_cmp_and_jump (adjusted_op0, const0_rtx, GT, compute_mode, label3);
@@ -4551,7 +4551,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
quotient, 0, OPTAB_LIB_WIDEN);
if (tem != quotient)
emit_move_insn (quotient, tem);
- emit_jump_insn (gen_jump (label5));
+ emit_jump_insn (targetm.gen_jump (label5));
emit_barrier ();
emit_label (label3);
expand_dec (adjusted_op0, const1_rtx);
@@ -4645,7 +4645,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
do_cmp_and_jump (adjusted_op0, const0_rtx, NE,
compute_mode, label1);
emit_move_insn (quotient, const0_rtx);
- emit_jump_insn (gen_jump (label2));
+ emit_jump_insn (targetm.gen_jump (label2));
emit_barrier ();
emit_label (label1);
expand_dec (adjusted_op0, const1_rtx);
@@ -4753,11 +4753,11 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
quotient, 0, OPTAB_LIB_WIDEN);
if (tem != quotient)
emit_move_insn (quotient, tem);
- emit_jump_insn (gen_jump (label5));
+ emit_jump_insn (targetm.gen_jump (label5));
emit_barrier ();
emit_label (label1);
expand_dec (adjusted_op0, const1_rtx);
- emit_jump_insn (gen_jump (label4));
+ emit_jump_insn (targetm.gen_jump (label4));
emit_barrier ();
emit_label (label2);
do_cmp_and_jump (adjusted_op0, const0_rtx, LT,
@@ -4766,7 +4766,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
quotient, 0, OPTAB_LIB_WIDEN);
if (tem != quotient)
emit_move_insn (quotient, tem);
- emit_jump_insn (gen_jump (label5));
+ emit_jump_insn (targetm.gen_jump (label5));
emit_barrier ();
emit_label (label3);
expand_inc (adjusted_op0, const1_rtx);
diff --git a/gcc/expr.c b/gcc/expr.c
index 408ae1a7a1f..5c0df44248d 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1491,10 +1491,6 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size,
void
move_block_to_reg (int regno, rtx x, int nregs, machine_mode mode)
{
- int i;
- rtx pat;
- rtx_insn *last;
-
if (nregs == 0)
return;
@@ -1502,12 +1498,12 @@ move_block_to_reg (int regno, rtx x, int nregs, machine_mode mode)
x = validize_mem (force_const_mem (mode, x));
/* See if the machine can do this with a load multiple insn. */
- if (HAVE_load_multiple)
+ if (targetm.have_load_multiple ())
{
- last = get_last_insn ();
- pat = gen_load_multiple (gen_rtx_REG (word_mode, regno), x,
- GEN_INT (nregs));
- if (pat)
+ rtx_insn *last = get_last_insn ();
+ rtx first = gen_rtx_REG (word_mode, regno);
+ if (rtx_insn *pat = targetm.gen_load_multiple (first, x,
+ GEN_INT (nregs)))
{
emit_insn (pat);
return;
@@ -1516,7 +1512,7 @@ move_block_to_reg (int regno, rtx x, int nregs, machine_mode mode)
delete_insns_since (last);
}
- for (i = 0; i < nregs; i++)
+ for (int i = 0; i < nregs; i++)
emit_move_insn (gen_rtx_REG (word_mode, regno + i),
operand_subword_force (x, i, mode));
}
@@ -1527,18 +1523,16 @@ move_block_to_reg (int regno, rtx x, int nregs, machine_mode mode)
void
move_block_from_reg (int regno, rtx x, int nregs)
{
- int i;
-
if (nregs == 0)
return;
/* See if the machine can do this with a store multiple insn. */
- if (HAVE_store_multiple)
+ if (targetm.have_store_multiple ())
{
rtx_insn *last = get_last_insn ();
- rtx pat = gen_store_multiple (x, gen_rtx_REG (word_mode, regno),
- GEN_INT (nregs));
- if (pat)
+ rtx first = gen_rtx_REG (word_mode, regno);
+ if (rtx_insn *pat = targetm.gen_store_multiple (x, first,
+ GEN_INT (nregs)))
{
emit_insn (pat);
return;
@@ -1547,7 +1541,7 @@ move_block_from_reg (int regno, rtx x, int nregs)
delete_insns_since (last);
}
- for (i = 0; i < nregs; i++)
+ for (int i = 0; i < nregs; i++)
{
rtx tem = operand_subword (x, i, 1, BLKmode);
@@ -5274,7 +5268,7 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
jumpifnot (TREE_OPERAND (exp, 0), lab1, -1);
store_expr_with_bounds (TREE_OPERAND (exp, 1), target, call_param_p,
nontemporal, btarget);
- emit_jump_insn (gen_jump (lab2));
+ emit_jump_insn (targetm.gen_jump (lab2));
emit_barrier ();
emit_label (lab1);
store_expr_with_bounds (TREE_OPERAND (exp, 2), target, call_param_p,
@@ -8916,7 +8910,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
return temp;
/* Use a compare and a jump for BLKmode comparisons, or for function
- type comparisons is HAVE_canonicalize_funcptr_for_compare. */
+ type comparisons is have_canonicalize_funcptr_for_compare. */
if ((target == 0
|| modifier == EXPAND_STACK_PARM
@@ -9206,7 +9200,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
modifier == EXPAND_STACK_PARM,
false);
- emit_jump_insn (gen_jump (lab1));
+ emit_jump_insn (targetm.gen_jump (lab1));
emit_barrier ();
emit_label (lab0);
store_expr (treeop2, temp,
@@ -10920,8 +10914,7 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
/* We won't bother with store-flag operations involving function pointers
when function pointers must be canonicalized before comparisons. */
-#ifdef HAVE_canonicalize_funcptr_for_compare
- if (HAVE_canonicalize_funcptr_for_compare
+ if (targetm.have_canonicalize_funcptr_for_compare ()
&& ((TREE_CODE (TREE_TYPE (arg0)) == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (TREE_TYPE (arg0)))
== FUNCTION_TYPE))
@@ -10929,7 +10922,6 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
&& (TREE_CODE (TREE_TYPE (TREE_TYPE (arg1)))
== FUNCTION_TYPE))))
return 0;
-#endif
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
diff --git a/gcc/final.c b/gcc/final.c
index a4b0f36c624..fe2d6adb3ba 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1803,12 +1803,8 @@ final_start_function (rtx_insn *first, FILE *file,
if the profiling code comes after the prologue. */
if (targetm.profile_before_prologue () && crtl->profile)
{
- if (targetm.asm_out.function_prologue
- == default_function_pro_epilogue
-#ifdef HAVE_prologue
- && HAVE_prologue
-#endif
- )
+ if (targetm.asm_out.function_prologue == default_function_pro_epilogue
+ && targetm.have_prologue ())
{
rtx_insn *insn;
for (insn = first; insn; insn = NEXT_INSN (insn))
@@ -1864,9 +1860,7 @@ final_start_function (rtx_insn *first, FILE *file,
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
-#ifdef HAVE_prologue
- if (! HAVE_prologue)
-#endif
+ if (! targetm.have_prologue ())
profile_after_prologue (file);
}
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 7b9502e2d38..5da6ed3e5d3 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -4488,14 +4488,12 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
{
tree etype = TREE_TYPE (exp), value;
-#ifdef HAVE_canonicalize_funcptr_for_compare
/* Disable this optimization for function pointer expressions
on targets that require function pointer canonicalization. */
- if (HAVE_canonicalize_funcptr_for_compare
+ if (targetm.have_canonicalize_funcptr_for_compare ()
&& TREE_CODE (etype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (etype)) == FUNCTION_TYPE)
return NULL_TREE;
-#endif
if (! in_p)
{
@@ -6964,14 +6962,12 @@ fold_widened_comparison (location_t loc, enum tree_code code,
return NULL_TREE;
shorter_type = TREE_TYPE (arg0_unw);
-#ifdef HAVE_canonicalize_funcptr_for_compare
/* Disable this optimization if we're casting a function pointer
type on targets that require function pointer canonicalization. */
- if (HAVE_canonicalize_funcptr_for_compare
+ if (targetm.have_canonicalize_funcptr_for_compare ()
&& TREE_CODE (shorter_type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (shorter_type)) == FUNCTION_TYPE)
return NULL_TREE;
-#endif
if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
return NULL_TREE;
@@ -7059,14 +7055,12 @@ fold_sign_changed_comparison (location_t loc, enum tree_code code, tree type,
arg0_inner = TREE_OPERAND (arg0, 0);
inner_type = TREE_TYPE (arg0_inner);
-#ifdef HAVE_canonicalize_funcptr_for_compare
/* Disable this optimization if we're casting a function pointer
type on targets that require function pointer canonicalization. */
- if (HAVE_canonicalize_funcptr_for_compare
+ if (targetm.have_canonicalize_funcptr_for_compare ()
&& TREE_CODE (inner_type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE)
return NULL_TREE;
-#endif
if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
return NULL_TREE;
@@ -8131,9 +8125,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
TREE_TYPE (targ0),
targ0));
}
- /* ABS_EXPR<ABS_EXPR<x>> = ABS_EXPR<x> even if flag_wrapv is on. */
- else if (TREE_CODE (arg0) == ABS_EXPR)
- return arg0;
/* Strip sign ops from argument. */
if (TREE_CODE (type) == REAL_TYPE)
@@ -8161,33 +8152,14 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
return NULL_TREE;
case BIT_NOT_EXPR:
- /* Convert ~ (-A) to A - 1. */
- if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
- return fold_build2_loc (loc, MINUS_EXPR, type,
- fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)),
- build_int_cst (type, 1));
- /* Convert ~ (A - 1) or ~ (A + -1) to -A. */
- else if (INTEGRAL_TYPE_P (type)
- && ((TREE_CODE (arg0) == MINUS_EXPR
- && integer_onep (TREE_OPERAND (arg0, 1)))
- || (TREE_CODE (arg0) == PLUS_EXPR
- && integer_all_onesp (TREE_OPERAND (arg0, 1)))))
- {
- /* Perform the negation in ARG0's type and only then convert
- to TYPE as to avoid introducing undefined behavior. */
- tree t = fold_build1_loc (loc, NEGATE_EXPR,
- TREE_TYPE (TREE_OPERAND (arg0, 0)),
- TREE_OPERAND (arg0, 0));
- return fold_convert_loc (loc, type, t);
- }
/* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */
- else if (TREE_CODE (arg0) == BIT_XOR_EXPR
- && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)))))
+ if (TREE_CODE (arg0) == BIT_XOR_EXPR
+ && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 0)))))
return fold_build2_loc (loc, BIT_XOR_EXPR, type, tem,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 1)));
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (arg0, 1)));
else if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
fold_convert_loc (loc, type,
@@ -10509,19 +10481,6 @@ fold_binary_loc (location_t loc,
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
- /* X - (X / Y) * Y is X % Y. */
- if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
- && TREE_CODE (arg1) == MULT_EXPR
- && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
- && operand_equal_p (arg0,
- TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
- && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, 0), 1),
- TREE_OPERAND (arg1, 1), 0))
- return
- fold_convert_loc (loc, type,
- fold_build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE (arg0),
- arg0, TREE_OPERAND (arg1, 1)));
-
if (! FLOAT_TYPE_P (type))
{
/* Fold A - (A & B) into ~B & A. */
@@ -10941,24 +10900,6 @@ fold_binary_loc (location_t loc,
case BIT_IOR_EXPR:
bit_ior:
- /* ~X | X is -1. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- {
- t1 = build_zero_cst (type);
- t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
- return omit_one_operand_loc (loc, type, t1, arg1);
- }
-
- /* X | ~X is -1. */
- if (TREE_CODE (arg1) == BIT_NOT_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- {
- t1 = build_zero_cst (type);
- t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
- return omit_one_operand_loc (loc, type, t1, arg0);
- }
-
/* Canonicalize (X & C1) | C2. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
@@ -11033,131 +10974,11 @@ fold_binary_loc (location_t loc,
if (t1 != NULL_TREE)
return t1;
- /* Convert (or (not arg0) (not arg1)) to (not (and (arg0) (arg1))).
-
- This results in more efficient code for machines without a NAND
- instruction. Combine will canonicalize to the first form
- which will allow use of NAND instructions provided by the
- backend if they exist. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == BIT_NOT_EXPR)
- {
- return
- fold_build1_loc (loc, BIT_NOT_EXPR, type,
- build2 (BIT_AND_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0))));
- }
-
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
case BIT_XOR_EXPR:
- /* ~X ^ X is -1. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- {
- t1 = build_zero_cst (type);
- t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
- return omit_one_operand_loc (loc, type, t1, arg1);
- }
-
- /* X ^ ~X is -1. */
- if (TREE_CODE (arg1) == BIT_NOT_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- {
- t1 = build_zero_cst (type);
- t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
- return omit_one_operand_loc (loc, type, t1, arg0);
- }
-
- /* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
- with a constant, and the two constants have no bits in common,
- we should treat this as a BIT_IOR_EXPR since this may produce more
- simplifications. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == BIT_AND_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
- && wi::bit_and (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1)) == 0)
- {
- code = BIT_IOR_EXPR;
- goto bit_ior;
- }
-
- /* (X | Y) ^ X -> Y & ~ X*/
- if (TREE_CODE (arg0) == BIT_IOR_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- {
- tree t2 = TREE_OPERAND (arg0, 1);
- t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1),
- arg1);
- t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, t1));
- return t1;
- }
-
- /* (Y | X) ^ X -> Y & ~ X*/
- if (TREE_CODE (arg0) == BIT_IOR_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- {
- tree t2 = TREE_OPERAND (arg0, 0);
- t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1),
- arg1);
- t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, t1));
- return t1;
- }
-
- /* X ^ (X | Y) -> Y & ~ X*/
- if (TREE_CODE (arg1) == BIT_IOR_EXPR
- && operand_equal_p (TREE_OPERAND (arg1, 0), arg0, 0))
- {
- tree t2 = TREE_OPERAND (arg1, 1);
- t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg0),
- arg0);
- t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, t1));
- return t1;
- }
-
- /* X ^ (Y | X) -> Y & ~ X*/
- if (TREE_CODE (arg1) == BIT_IOR_EXPR
- && operand_equal_p (TREE_OPERAND (arg1, 1), arg0, 0))
- {
- tree t2 = TREE_OPERAND (arg1, 0);
- t1 = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg0),
- arg0);
- t1 = fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, t1));
- return t1;
- }
-
- /* Convert ~X ^ ~Y to X ^ Y. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == BIT_NOT_EXPR)
- return fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0)));
-
- /* Convert ~X ^ C to X ^ ~C. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == INTEGER_CST)
- return fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_build1_loc (loc, BIT_NOT_EXPR, type, arg1));
-
/* Fold (X & 1) ^ 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& INTEGRAL_TYPE_P (type)
@@ -11166,45 +10987,6 @@ fold_binary_loc (location_t loc,
return fold_build2_loc (loc, EQ_EXPR, type, arg0,
build_zero_cst (TREE_TYPE (arg0)));
- /* Fold (X & Y) ^ Y as ~X & Y. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- {
- tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
- fold_convert_loc (loc, type, arg1));
- }
- /* Fold (X & Y) ^ X as ~Y & X. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
- && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
- {
- tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
- fold_convert_loc (loc, type, arg1));
- }
- /* Fold X ^ (X & Y) as X & ~Y. */
- if (TREE_CODE (arg1) == BIT_AND_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- {
- tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, arg0),
- fold_build1_loc (loc, BIT_NOT_EXPR, type, tem));
- }
- /* Fold X ^ (Y & X) as ~Y & X. */
- if (TREE_CODE (arg1) == BIT_AND_EXPR
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
- && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
- {
- tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
- fold_convert_loc (loc, type, arg0));
- }
-
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
@@ -11469,23 +11251,6 @@ fold_binary_loc (location_t loc,
fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
}
- /* Convert (and (not arg0) (not arg1)) to (not (or (arg0) (arg1))).
-
- This results in more efficient code for machines without a NOR
- instruction. Combine will canonicalize to the first form
- which will allow use of NOR instructions provided by the
- backend if they exist. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
- && TREE_CODE (arg1) == BIT_NOT_EXPR)
- {
- return fold_build1_loc (loc, BIT_NOT_EXPR, type,
- build2 (BIT_IOR_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0))));
- }
-
/* If arg0 is derived from the address of an object or function, we may
be able to fold this expression using the object or function's
alignment. */
diff --git a/gcc/function.c b/gcc/function.c
index cffe32322d2..8134c4e7067 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -4891,7 +4891,7 @@ stack_protect_epilogue (void)
/* Allow the target to compare Y with X without leaking either into
a register. */
- switch ((int) (HAVE_stack_protect_test != 0))
+ switch (HAVE_stack_protect_test != 0)
{
case 1:
tmp = gen_stack_protect_test (x, y, label);
@@ -5210,20 +5210,6 @@ use_return_register (void)
diddle_return_value (do_use_return_reg, NULL);
}
-/* Possibly warn about unused parameters. */
-void
-do_warn_unused_parameter (tree fn)
-{
- tree decl;
-
- for (decl = DECL_ARGUMENTS (fn);
- decl; decl = DECL_CHAIN (decl))
- if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
- && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)
- && !TREE_NO_WARNING (decl))
- warning (OPT_Wunused_parameter, "unused parameter %q+D", decl);
-}
-
/* Set the location of the insn chain starting at INSN to LOC. */
static void
@@ -5878,11 +5864,10 @@ thread_prologue_and_epilogue_insns (void)
}
prologue_seq = NULL;
-#ifdef HAVE_prologue
- if (HAVE_prologue)
+ if (targetm.have_prologue ())
{
start_sequence ();
- rtx_insn *seq = safe_as_a <rtx_insn *> (gen_prologue ());
+ rtx_insn *seq = targetm.gen_prologue ();
emit_insn (seq);
/* Insert an explicit USE for the frame pointer
@@ -5904,7 +5889,6 @@ thread_prologue_and_epilogue_insns (void)
end_sequence ();
set_insn_locations (prologue_seq, prologue_location);
}
-#endif
bitmap_initialize (&bb_flags, &bitmap_default_obstack);
@@ -6009,11 +5993,11 @@ thread_prologue_and_epilogue_insns (void)
if (exit_fallthru_edge == NULL)
goto epilogue_done;
- if (HAVE_epilogue)
+ if (targetm.have_epilogue ())
{
start_sequence ();
epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG);
- rtx_insn *seq = as_a <rtx_insn *> (gen_epilogue ());
+ rtx_insn *seq = targetm.gen_epilogue ();
if (seq)
emit_jump_insn (seq);
@@ -6084,7 +6068,6 @@ epilogue_done:
convert_to_simple_return (entry_edge, orig_entry_edge, bb_flags,
returnjump, unconverted_simple_returns);
-#ifdef HAVE_sibcall_epilogue
/* Emit sibling epilogues before any sibling call sites. */
for (ei = ei_start (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); (e =
ei_safe_edge (ei));
@@ -6092,7 +6075,6 @@ epilogue_done:
{
basic_block bb = e->src;
rtx_insn *insn = BB_END (bb);
- rtx ep_seq;
if (!CALL_P (insn)
|| ! SIBLING_CALL_P (insn)
@@ -6104,8 +6086,7 @@ epilogue_done:
continue;
}
- ep_seq = gen_sibcall_epilogue ();
- if (ep_seq)
+ if (rtx_insn *ep_seq = targetm.gen_sibcall_epilogue ())
{
start_sequence ();
emit_note (NOTE_INSN_EPILOGUE_BEG);
@@ -6123,7 +6104,6 @@ epilogue_done:
}
ei_next (&ei);
}
-#endif
if (epilogue_end)
{
@@ -6157,10 +6137,10 @@ epilogue_done:
void
reposition_prologue_and_epilogue_notes (void)
{
-#if ! defined (HAVE_prologue) && ! defined (HAVE_sibcall_epilogue)
- if (!HAVE_epilogue)
+ if (!targetm.have_prologue ()
+ && !targetm.have_epilogue ()
+ && !targetm.have_sibcall_epilogue ())
return;
-#endif
/* Since the hash table is created on demand, the fact that it is
non-null is a signal that it is non-empty. */
diff --git a/gcc/function.h b/gcc/function.h
index dc4a8cc7c0f..e92c17c6fcc 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -614,7 +614,6 @@ extern void expand_dummy_function_end (void);
extern void thread_prologue_and_epilogue_insns (void);
extern void diddle_return_value (void (*)(rtx, void*), void*);
extern void clobber_return_register (void);
-extern void do_warn_unused_parameter (tree);
extern void expand_function_end (void);
extern rtx get_arg_pointer_save_area (void);
extern void maybe_copy_prologue_epilogue_insn (rtx, rtx);
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index 423cd034558..6d8e2427b1b 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -1736,6 +1736,10 @@ expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth,
if (gimple)
{
+ if (*operation == CONVERT_EXPR)
+ fprintf (f, " if (%s != TREE_TYPE (ops%d[0])\n"
+ " && !useless_type_conversion_p (%s, TREE_TYPE (ops%d[0])))\n"
+ " {\n", type, depth, type, depth);
/* ??? Building a stmt can fail for various reasons here, seq being
NULL or the stmt referencing SSA names occuring in abnormal PHIs.
So if we fail here we should continue matching other patterns. */
@@ -1748,9 +1752,15 @@ expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth,
ops.length (), type);
fprintf (f, " res = maybe_push_res_to_seq (tem_code, %s, tem_ops, seq);\n"
" if (!res) return false;\n", type);
+ if (*operation == CONVERT_EXPR)
+ fprintf (f, " }\n"
+ " else\n"
+ " res = ops%d[0];\n", depth);
}
else
{
+ if (*operation == CONVERT_EXPR)
+ fprintf (f, " if (TREE_TYPE (ops%d[0]) != %s)\n", depth, type);
if (operation->kind == id_base::CODE)
fprintf (f, " res = fold_build%d_loc (loc, %s, %s",
ops.length(), opr, type);
@@ -1760,6 +1770,9 @@ expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth,
for (unsigned i = 0; i < ops.length (); ++i)
fprintf (f, ", ops%d[%u]", depth, i);
fprintf (f, ");\n");
+ if (*operation == CONVERT_EXPR)
+ fprintf (f, " else\n"
+ " res = ops%d[0];\n", depth);
}
fprintf (f, "%s = res;\n", dest);
fprintf (f, "}\n");
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index fd6e3e929e6..e685cc8a1af 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -8120,7 +8120,7 @@ init_before_recovery (basic_block *before_recovery_ptr)
EDGE_FALLTHRU);
rtx_code_label *label = block_label (empty);
- rtx_jump_insn *x = emit_jump_insn_after (gen_jump (label),
+ rtx_jump_insn *x = emit_jump_insn_after (targetm.gen_jump (label),
BB_END (single));
JUMP_LABEL (x) = label;
LABEL_NUSES (label)++;
@@ -8198,7 +8198,8 @@ sched_create_recovery_edges (basic_block first_bb, basic_block rec,
make_edge (first_bb, rec, edge_flags);
rtx_code_label *label = block_label (second_bb);
- rtx_jump_insn *jump = emit_jump_insn_after (gen_jump (label), BB_END (rec));
+ rtx_jump_insn *jump = emit_jump_insn_after (targetm.gen_jump (label),
+ BB_END (rec));
JUMP_LABEL (jump) = label;
LABEL_NUSES (label)++;
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 7d4ad934003..6e20557d52b 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -3824,10 +3824,9 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
single_succ_edge (test_bb)->flags |= EDGE_FALLTHRU;
else if (trap_bb == then_bb)
{
- rtx lab;
-
- lab = JUMP_LABEL (jump);
- rtx_jump_insn *newjump = emit_jump_insn_after (gen_jump (lab), jump);
+ rtx lab = JUMP_LABEL (jump);
+ rtx_insn *seq = targetm.gen_jump (lab);
+ rtx_jump_insn *newjump = emit_jump_insn_after (seq, jump);
LABEL_NUSES (lab) += 1;
JUMP_LABEL (newjump) = lab;
emit_barrier_after (newjump);
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index e394047fc73..325f3b8883f 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -1,3 +1,183 @@
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ * docs/cp/topics/functions.rst (Blocks): Add switch statements to
+ list of ways to terminate a block.
+ (gccjit::block::end_with_switch): Add function description.
+ (gccjit::case_): Add class.
+ (gccjit::context::new_case): Add function description.
+ * docs/cp/topics/objects.rst: Add "case_" to class hierarchy.
+ * docs/topics/compatibility.rst (LIBGCCJIT_ABI_3): New.
+ * docs/topics/functions.rst (Blocks): Add switch statements to
+ list of ways to terminate a block.
+ (gcc_jit_block_end_with_switch): Add function description.
+ (gcc_jit_case): Add type.
+ (gcc_jit_context_new_case): Add function description.
+ (gcc_jit_case_as_object): Add function description.
+ * docs/topics/objects.rst: Add gcc_jit_case to class hierarchy.
+ * docs/_build/texinfo/libgccjit.texi: Regenerate.
+ * jit-common.h (gcc::jit::recording::case_): Add forward decl.
+ (gcc::jit::playback::case_): Add forward decl.
+ * jit-playback.c (add_case): New function.
+ (gcc::jit::playback::block::add_switch): New function.
+ * jit-playback.h (gcc::jit::playback::case_): New struct.
+ (gcc::jit::playback::block::get_function): New method.
+ (gcc::jit::playback::block::add_switch): New method.
+ * jit-recording.c: Within namespace gcc::jit...
+ (recording::context::new_case): New method.
+ (recording::function::validate): Update for change to
+ get_successor_blocks.
+ (recording::block::end_with_switch): New method.
+ (recording::block::get_successor_blocks): Update to support an
+ arbitrary number of successor blocks.
+ (recording::block::dump_edges_to_dot): Likewise.
+ (memento_of_new_rvalue_from_const <int>::get_wide_int): New.
+ (memento_of_new_rvalue_from_const <long>::get_wide_int): New.
+ (memento_of_new_rvalue_from_const <double>::get_wide_int): New.
+ (memento_of_new_rvalue_from_const <void *>::get_wide_int): New.
+ (recording::statement::get_successor_blocks): Update to support an
+ arbitrary number of successor blocks.
+ (recording::conditional::get_successor_blocks): Likewise.
+ (recording::jump::get_successor_blocks): Likewise.
+ (recording::return_::get_successor_blocks): Likewise.
+ (recording::case_::write_reproducer): New.
+ (recording::case_::make_debug_string): New.
+ (recording::switch_::switch_): New.
+ (recording::switch_::replay_into): New.
+ (recording::switch_::get_successor_blocks): New.
+ (recording::switch_::make_debug_string): New.
+ (recording::switch_::write_reproducer): New.
+ * jit-recording.h: Within namespace gcc::jit::recording...
+ (context::new_case): New.
+ (rvalue::is_constant): New.
+ (rvalue::get_wide_int): New.
+ (block::end_with_switch): New.
+ (block::get_successor_blocks): Update to support an arbitrary
+ number of successor blocks.
+ (memento_of_new_rvalue_from_const::is_constant): New.
+ (memento_of_new_rvalue_from_const::get_wide_int): New.
+ (statement::get_successor_blocks): Update to support an arbitrary
+ number of successor blocks.
+ (conditional::get_successor_blocks): Likewise.
+ (jump::get_successor_blocks): Likewise.
+ (return_::get_successor_blocks): Likewise.
+ (case_): New subclass of memento.
+ (switch_): New subclass of statement.
+ * libgccjit++.h (gccjit::case_): New subclass of gccjit::object.
+ (gccjit::context::new_case): New method.
+ (gccjit::block::end_with_switch): New method.
+ (gccjit::case_::case): New ctors.
+ (gccjit::case_::get_inner_case): New method.
+ * libgccjit.c: Include "typed-splay-tree.h"
+ (struct gcc_jit_case): New.
+ (gcc_jit_context_new_case): New function.
+ (gcc_jit_case_as_object): New function.
+ (valid_dest_for_switch): New function.
+ (valid_case_for_switch): New function.
+ (class api_call_validator): New class.
+ (class case_range_validator): New class.
+ (case_range_validator::case_range_validator): New.
+ (case_range_validator::validate): New.
+ (case_range_validator::case_compare): New.
+ (case_range_validator::get_wide_int): new.
+ (gcc_jit_block_end_with_switch): New.
+ * libgccjit.h: Add gcc_jit_case to class hierarchy comment.
+ (gcc_jit_case): New typedef.
+ (gcc_jit_context_new_case): New function.
+ (gcc_jit_case_as_object): New function.
+ (gcc_jit_block_end_with_switch): New function.
+ (LIBGCCJIT_HAVE_SWITCH_STATEMENTS): New.
+ * libgccjit.map: Add gcc_jit_block_end_with_switch,
+ gcc_jit_case_as_object and gcc_jit_context_new_case.
+
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/66546
+ * docs/cp/topics/contexts.rst
+ (gccjit::context::set_bool_allow_unreachable_blocks): New.
+ * docs/topics/compatibility.rst (LIBGCCJIT_ABI_2): New.
+ * docs/topics/contexts.rst (Options): Add notes discussing the
+ transition from enums to entrypoints for new options.
+ (gcc_jit_context_set_bool_allow_unreachable_blocks): New.
+ * docs/_build/texinfo/libgccjit.texi: Regenerate.
+ * jit-common.h (gcc::jit::inner_bool_option): New enum.
+ * jit-recording.c: Within namespace gcc::jit...
+ (recording::context::context): Handle m_inner_bool_options.
+ (recording::context::set_inner_bool_option): New.
+ (inner_bool_option_reproducer_strings): New.
+ (recording::context::log_all_options): Log the "inner" bool
+ options.
+ (recording::context::log_inner_bool_option): New.
+ (recording::context::dump_reproducer_to_file): Write initializers
+ for "inner" bool options.
+ (recording::function::validate): Don't check for block
+ reachability if INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS is set.
+ * jit-recording.h: Within namespace gcc::jit...
+ (recording::context::set_inner_bool_option): New.
+ (recording::context::get_inner_bool_option): New.
+ (recording::context::log_inner_bool_option): New.
+ (recording::context::m_inner_bool_options): New.
+ * libgccjit++.h
+ (gccjit::context::set_bool_allow_unreachable_blocks): New.
+ * libgccjit.c
+ (gcc_jit_context_set_bool_allow_unreachable_blocks): New.
+ * libgccjit.h: Add note about options present in the
+ initial release of libgccjit.
+ (gcc_jit_context_set_bool_allow_unreachable_blocks): New API
+ entrypoint.
+ (LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks):
+ New macro.
+ * libgccjit.map (LIBGCCJIT_ABI_2): New, containing...
+ (gcc_jit_context_set_bool_allow_unreachable_blocks): ...this new
+ entrypoint.
+
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/66628
+ * docs/cp/topics/contexts.rst (Additional command-line options):
+ New section.
+ * docs/topics/compatibility.rst: New file.
+ * docs/topics/contexts.rst (Additional command-line options): New
+ section.
+ * docs/topics/index.rst: Add compatibility.rst.
+ * docs/_build/texinfo/libgccjit.texi: Regenerate.
+ * jit-playback.c (make_fake_args): Add call to
+ append_command_line_options.
+ * jit-recording.c: Within namespace gcc::jit...
+ (recording::context::~context): Free the optnames within
+ m_command_line_options.
+ (recording::context::set_bool_option): Likewise.
+ (recording::context::add_command_line_option): New method.
+ (recording::context::append_command_line_options): New method.
+ (recording::context::dump_reproducer_to_file): Add command-line
+ options.
+ * jit-recording.h: Within namespace gcc::jit...
+ (recording::context::add_command_line_option): New method.
+ (recording::context::append_command_line_options): New method.
+ (recording::context::m_command_line_options): New field.
+ * libgccjit++.h (gccjit::context::add_command_line_option): New
+ method.
+ * libgccjit.c (gcc_jit_context_add_command_line_option): New API
+ entrypoint.
+ * libgccjit.h (gcc_jit_context_add_command_line_option): New API
+ entrypoint.
+ (LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option): New
+ macro.
+ * libgccjit.map: Put existing symbols within LIBGCCJIT_ABI_0; add
+ LIBGCCJIT_ABI_1 and gcc_jit_context_add_command_line_option.
+
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ * jit-recording.c
+ (gcc::jit::recording::context::dump_reproducer_to_file):
+ Add pragma to generated reproducers to disable -Wunused-variable.
+ Fix handling of NULL string options.
+
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ * docs/cp/topics/expressions.rst: Remove stray semicolon.
+ * docs/cp/topics/functions.rst: Remove stray backslash.
+ * docs/_build/texinfo/libgccjit.texi: Regenerate.
+
2015-06-25 Andrew MacLeod <amacleod@redhat.com>
* dummy-frontend.c: Remove ipa-ref.h and plugin-api.h from include list.
diff --git a/gcc/jit/docs/_build/texinfo/libgccjit.texi b/gcc/jit/docs/_build/texinfo/libgccjit.texi
index ac530351702..212df10ff05 100644
--- a/gcc/jit/docs/_build/texinfo/libgccjit.texi
+++ b/gcc/jit/docs/_build/texinfo/libgccjit.texi
@@ -19,7 +19,7 @@
@copying
@quotation
-libgccjit 5.0.0 (experimental 20150409), April 09, 2015
+libgccjit 6.0.0 (experimental 20150630), June 30, 2015
David Malcolm
@@ -168,6 +168,7 @@ Topic Reference
* Creating and using functions::
* Source Locations::
* Compiling a context::
+* ABI and API compatibility::
Compilation contexts
@@ -182,6 +183,7 @@ Options
* String Options::
* Boolean options::
* Integer options::
+* Additional command-line options::
Types
@@ -224,6 +226,17 @@ Compiling a context
* In-memory compilation::
* Ahead-of-time compilation::
+ABI and API compatibility
+
+* ABI symbol tags::
+
+ABI symbol tags
+
+* LIBGCCJIT_ABI_0::
+* LIBGCCJIT_ABI_1::
+* LIBGCCJIT_ABI_2::
+* LIBGCCJIT_ABI_3::
+
C++ bindings for libgccjit
* Tutorial: Tutorial<2>.
@@ -289,6 +302,7 @@ Options
* String Options: String Options<2>.
* Boolean options: Boolean options<2>.
* Integer options: Integer options<2>.
+* Additional command-line options: Additional command-line options<2>.
Types
@@ -4836,6 +4850,7 @@ and to a dynamic library. See the documentation of
* Creating and using functions::
* Source Locations::
* Compiling a context::
+* ABI and API compatibility::
Compilation contexts
@@ -4850,6 +4865,7 @@ Options
* String Options::
* Boolean options::
* Integer options::
+* Additional command-line options::
Types
@@ -4892,6 +4908,17 @@ Compiling a context
* In-memory compilation::
* Ahead-of-time compilation::
+ABI and API compatibility
+
+* ABI symbol tags::
+
+ABI symbol tags
+
+* LIBGCCJIT_ABI_0::
+* LIBGCCJIT_ABI_1::
+* LIBGCCJIT_ABI_2::
+* LIBGCCJIT_ABI_3::
+
@end menu
@@ -5227,10 +5254,20 @@ It exists primarily for writing the library's own test suite.
@subsection Options
+Options present in the initial release of libgccjit were handled using
+enums, whereas those added subsequently have their own per-option API
+entrypoints.
+
+Adding entrypoints for each new option means that client code that use
+the new options can be identified directly from binary metadata, which
+would not be possible if we instead extended the various
+@code{enum gcc_jit_*_option}.
+
@menu
* String Options::
* Boolean options::
* Integer options::
+* Additional command-line options::
@end menu
@@ -5250,7 +5287,7 @@ Set a string option of the context.
@deffn {C Type} enum gcc_jit_str_option
@end deffn
-There is currently just one string option:
+There is just one string option specified this way:
@geindex GCC_JIT_STR_OPTION_PROGNAME (C macro)
@anchor{topics/contexts GCC_JIT_STR_OPTION_PROGNAME}@anchor{63}
@@ -5428,8 +5465,27 @@ written to the filesystem, and will display their location on stderr.
@end deffn
@end deffn
-@node Integer options,,Boolean options,Options<2>
-@anchor{topics/contexts integer-options}@anchor{6b}
+@geindex gcc_jit_context_set_bool_allow_unreachable_blocks (C function)
+@anchor{topics/contexts gcc_jit_context_set_bool_allow_unreachable_blocks}@anchor{6b}
+@deffn {C Function} void gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context@w{ }*ctxt, int@w{ }bool_value)
+
+By default, libgccjit will issue an error about unreachable blocks
+within a function.
+
+This entrypoint can be used to disable that error.
+
+This entrypoint was added in @pxref{6c,,LIBGCCJIT_ABI_2}; you can test for
+its presence using
+
+@example
+#ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
+@end example
+
+@noindent
+@end deffn
+
+@node Integer options,Additional command-line options,Boolean options,Options<2>
+@anchor{topics/contexts integer-options}@anchor{6d}
@subsubsection Integer options
@@ -5440,11 +5496,11 @@ written to the filesystem, and will display their location on stderr.
Set an integer option of the context.
@geindex gcc_jit_int_option (C type)
-@anchor{topics/contexts gcc_jit_int_option}@anchor{6c}
+@anchor{topics/contexts gcc_jit_int_option}@anchor{6e}
@deffn {C Type} enum gcc_jit_int_option
@end deffn
-There is currently just one integer option:
+There is just one integer option specified this way:
@geindex GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL (C macro)
@anchor{topics/contexts GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}@anchor{1f}
@@ -5459,6 +5515,50 @@ The default value is 0 (unoptimized).
@end deffn
@end deffn
+@node Additional command-line options,,Integer options,Options<2>
+@anchor{topics/contexts additional-command-line-options}@anchor{6f}
+@subsubsection Additional command-line options
+
+
+@geindex gcc_jit_context_add_command_line_option (C function)
+@anchor{topics/contexts gcc_jit_context_add_command_line_option}@anchor{70}
+@deffn {C Function} void gcc_jit_context_add_command_line_option (gcc_jit_context@w{ }*ctxt, const char@w{ }*optname)
+
+Add an arbitrary gcc command-line option to the context, for use
+by @pxref{15,,gcc_jit_context_compile()} and
+@pxref{4a,,gcc_jit_context_compile_to_file()}.
+
+The parameter @code{optname} must be non-NULL. The underlying buffer is
+copied, so that it does not need to outlive the call.
+
+Extra options added by @cite{gcc_jit_context_add_command_line_option} are
+applied @emph{after} the regular options above, potentially overriding them.
+Options from parent contexts are inherited by child contexts; options
+from the parent are applied @emph{before} those from the child.
+
+For example:
+
+@example
+gcc_jit_context_add_command_line_option (ctxt, "-ffast-math");
+gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm");
+@end example
+
+@noindent
+
+Note that only some options are likely to be meaningful; there is no
+"frontend" within libgccjit, so typically only those affecting
+optimization and code-generation are likely to be useful.
+
+This entrypoint was added in @pxref{71,,LIBGCCJIT_ABI_1}; you can test for
+its presence using
+
+@example
+#ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
+@end example
+
+@noindent
+@end deffn
+
@c Copyright (C) 2014-2015 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -5477,7 +5577,7 @@ The default value is 0 (unoptimized).
@c <http://www.gnu.org/licenses/>.
@node Objects,Types,Compilation contexts,Topic Reference
-@anchor{topics/objects objects}@anchor{6d}@anchor{topics/objects doc}@anchor{6e}
+@anchor{topics/objects objects}@anchor{72}@anchor{topics/objects doc}@anchor{73}
@section Objects
@@ -5521,6 +5621,7 @@ looks like this:
+- gcc_jit_rvalue
+- gcc_jit_lvalue
+- gcc_jit_param
+ +- gcc_jit_case
@end example
@noindent
@@ -5537,7 +5638,7 @@ gcc_jit_object *obj = gcc_jit_type_as_object (int_type);
The object "base class" has the following operations:
@geindex gcc_jit_object_get_context (C function)
-@anchor{topics/objects gcc_jit_object_get_context}@anchor{6f}
+@anchor{topics/objects gcc_jit_object_get_context}@anchor{74}
@deffn {C Function} gcc_jit_context *gcc_jit_object_get_context (gcc_jit_object@w{ }*obj)
Which context is "obj" within?
@@ -5593,7 +5694,7 @@ object's context is released.
@c <http://www.gnu.org/licenses/>.
@node Types,Expressions,Objects,Topic Reference
-@anchor{topics/types doc}@anchor{70}@anchor{topics/types types}@anchor{71}
+@anchor{topics/types doc}@anchor{75}@anchor{topics/types types}@anchor{76}
@section Types
@@ -5630,7 +5731,7 @@ See @pxref{b,,gcc_jit_context_get_type()} for the available types.
@item
derived types can be accessed by using functions such as
-@pxref{72,,gcc_jit_type_get_pointer()} and @pxref{73,,gcc_jit_type_get_const()}:
+@pxref{77,,gcc_jit_type_get_pointer()} and @pxref{78,,gcc_jit_type_get_const()}:
@example
gcc_jit_type *const_int_star = gcc_jit_type_get_pointer (gcc_jit_type_get_const (int_type));
@@ -5651,7 +5752,7 @@ by creating structures (see below).
@end menu
@node Standard types,Pointers const and volatile,,Types
-@anchor{topics/types standard-types}@anchor{74}
+@anchor{topics/types standard-types}@anchor{79}
@subsection Standard types
@@ -5856,66 +5957,66 @@ C99's @code{_Complex long double}
@end deffn
@geindex gcc_jit_context_get_int_type (C function)
-@anchor{topics/types gcc_jit_context_get_int_type}@anchor{75}
+@anchor{topics/types gcc_jit_context_get_int_type}@anchor{7a}
@deffn {C Function} gcc_jit_type * gcc_jit_context_get_int_type (gcc_jit_context@w{ }*ctxt, int@w{ }num_bytes, int@w{ }is_signed)
Access the integer type of the given size.
@end deffn
@node Pointers const and volatile,Structures and unions,Standard types,Types
-@anchor{topics/types pointers-const-and-volatile}@anchor{76}
+@anchor{topics/types pointers-const-and-volatile}@anchor{7b}
@subsection Pointers, @cite{const}, and @cite{volatile}
@geindex gcc_jit_type_get_pointer (C function)
-@anchor{topics/types gcc_jit_type_get_pointer}@anchor{72}
+@anchor{topics/types gcc_jit_type_get_pointer}@anchor{77}
@deffn {C Function} gcc_jit_type *gcc_jit_type_get_pointer (gcc_jit_type@w{ }*type)
Given type "T", get type "T*".
@end deffn
@geindex gcc_jit_type_get_const (C function)
-@anchor{topics/types gcc_jit_type_get_const}@anchor{73}
+@anchor{topics/types gcc_jit_type_get_const}@anchor{78}
@deffn {C Function} gcc_jit_type *gcc_jit_type_get_const (gcc_jit_type@w{ }*type)
Given type "T", get type "const T".
@end deffn
@geindex gcc_jit_type_get_volatile (C function)
-@anchor{topics/types gcc_jit_type_get_volatile}@anchor{77}
+@anchor{topics/types gcc_jit_type_get_volatile}@anchor{7c}
@deffn {C Function} gcc_jit_type *gcc_jit_type_get_volatile (gcc_jit_type@w{ }*type)
Given type "T", get type "volatile T".
@end deffn
@geindex gcc_jit_context_new_array_type (C function)
-@anchor{topics/types gcc_jit_context_new_array_type}@anchor{78}
+@anchor{topics/types gcc_jit_context_new_array_type}@anchor{7d}
@deffn {C Function} gcc_jit_type * gcc_jit_context_new_array_type (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*element_type, int@w{ }num_elements)
Given type "T", get type "T[N]" (for a constant N).
@end deffn
@node Structures and unions,,Pointers const and volatile,Types
-@anchor{topics/types structures-and-unions}@anchor{79}
+@anchor{topics/types structures-and-unions}@anchor{7e}
@subsection Structures and unions
@geindex gcc_jit_struct (C type)
-@anchor{topics/types gcc_jit_struct}@anchor{7a}
+@anchor{topics/types gcc_jit_struct}@anchor{7f}
@deffn {C Type} gcc_jit_struct
@end deffn
A compound type analagous to a C @cite{struct}.
@geindex gcc_jit_field (C type)
-@anchor{topics/types gcc_jit_field}@anchor{7b}
+@anchor{topics/types gcc_jit_field}@anchor{80}
@deffn {C Type} gcc_jit_field
@end deffn
-A field within a @pxref{7a,,gcc_jit_struct}.
+A field within a @pxref{7f,,gcc_jit_struct}.
-You can model C @cite{struct} types by creating @pxref{7a,,gcc_jit_struct *} and
-@pxref{7b,,gcc_jit_field} instances, in either order:
+You can model C @cite{struct} types by creating @pxref{7f,,gcc_jit_struct *} and
+@pxref{80,,gcc_jit_field} instances, in either order:
@itemize *
@@ -5972,21 +6073,21 @@ gcc_jit_struct_set_fields (node, NULL, 2, fields);
@end itemize
@geindex gcc_jit_context_new_field (C function)
-@anchor{topics/types gcc_jit_context_new_field}@anchor{7c}
+@anchor{topics/types gcc_jit_context_new_field}@anchor{81}
@deffn {C Function} gcc_jit_field * gcc_jit_context_new_field (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_type@w{ }*type, const char@w{ }*name)
Construct a new field, with the given type and name.
@end deffn
@geindex gcc_jit_field_as_object (C function)
-@anchor{topics/types gcc_jit_field_as_object}@anchor{7d}
+@anchor{topics/types gcc_jit_field_as_object}@anchor{82}
@deffn {C Function} gcc_jit_object * gcc_jit_field_as_object (gcc_jit_field@w{ }*field)
Upcast from field to object.
@end deffn
@geindex gcc_jit_context_new_struct_type (C function)
-@anchor{topics/types gcc_jit_context_new_struct_type}@anchor{7e}
+@anchor{topics/types gcc_jit_context_new_struct_type}@anchor{83}
@deffn {C Function} gcc_jit_struct *gcc_jit_context_new_struct_type (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, const char@w{ }*name, int@w{ }num_fields, gcc_jit_field@w{ }**fields)
@quotation
@@ -5996,24 +6097,24 @@ Construct a new struct type, with the given name and fields.
@end deffn
@geindex gcc_jit_context_new_opaque_struct (C function)
-@anchor{topics/types gcc_jit_context_new_opaque_struct}@anchor{7f}
+@anchor{topics/types gcc_jit_context_new_opaque_struct}@anchor{84}
@deffn {C Function} gcc_jit_struct * gcc_jit_context_new_opaque_struct (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, const char@w{ }*name)
Construct a new struct type, with the given name, but without
specifying the fields. The fields can be omitted (in which case the
size of the struct is not known), or later specified using
-@pxref{80,,gcc_jit_struct_set_fields()}.
+@pxref{85,,gcc_jit_struct_set_fields()}.
@end deffn
@geindex gcc_jit_struct_as_type (C function)
-@anchor{topics/types gcc_jit_struct_as_type}@anchor{81}
+@anchor{topics/types gcc_jit_struct_as_type}@anchor{86}
@deffn {C Function} gcc_jit_type * gcc_jit_struct_as_type (gcc_jit_struct@w{ }*struct_type)
Upcast from struct to type.
@end deffn
@geindex gcc_jit_struct_set_fields (C function)
-@anchor{topics/types gcc_jit_struct_set_fields}@anchor{80}
+@anchor{topics/types gcc_jit_struct_set_fields}@anchor{85}
@deffn {C Function} void gcc_jit_struct_set_fields (gcc_jit_struct@w{ }*struct_type, gcc_jit_location@w{ }*loc, int@w{ }num_fields, gcc_jit_field@w{ }**fields)
Populate the fields of a formerly-opaque struct type.
@@ -6039,7 +6140,7 @@ This can only be called once on a given struct type.
@c <http://www.gnu.org/licenses/>.
@node Expressions,Creating and using functions,Types,Topic Reference
-@anchor{topics/expressions expressions}@anchor{82}@anchor{topics/expressions doc}@anchor{83}
+@anchor{topics/expressions expressions}@anchor{87}@anchor{topics/expressions doc}@anchor{88}
@section Expressions
@@ -6065,7 +6166,7 @@ Lvalues
@node Rvalues,Lvalues,,Expressions
-@anchor{topics/expressions rvalues}@anchor{84}
+@anchor{topics/expressions rvalues}@anchor{89}
@subsection Rvalues
@@ -6119,7 +6220,7 @@ Every rvalue has an associated type, and the API will check to ensure
that types match up correctly (otherwise the context will emit an error).
@geindex gcc_jit_rvalue_get_type (C function)
-@anchor{topics/expressions gcc_jit_rvalue_get_type}@anchor{85}
+@anchor{topics/expressions gcc_jit_rvalue_get_type}@anchor{8a}
@deffn {C Function} gcc_jit_type *gcc_jit_rvalue_get_type (gcc_jit_rvalue@w{ }*rvalue)
Get the type of this rvalue.
@@ -6143,7 +6244,7 @@ Upcast the given rvalue to be an object.
@end menu
@node Simple expressions,Unary Operations,,Rvalues
-@anchor{topics/expressions simple-expressions}@anchor{86}
+@anchor{topics/expressions simple-expressions}@anchor{8b}
@subsubsection Simple expressions
@@ -6156,7 +6257,7 @@ the given constant @code{int} value.
@end deffn
@geindex gcc_jit_context_new_rvalue_from_long (C function)
-@anchor{topics/expressions gcc_jit_context_new_rvalue_from_long}@anchor{87}
+@anchor{topics/expressions gcc_jit_context_new_rvalue_from_long}@anchor{8c}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_long (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*numeric_type, long@w{ }value)
Given a numeric type (integer or floating point), build an rvalue for
@@ -6200,14 +6301,14 @@ the given constant @code{double} value.
@end deffn
@geindex gcc_jit_context_new_rvalue_from_ptr (C function)
-@anchor{topics/expressions gcc_jit_context_new_rvalue_from_ptr}@anchor{88}
+@anchor{topics/expressions gcc_jit_context_new_rvalue_from_ptr}@anchor{8d}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*pointer_type, void@w{ }*value)
Given a pointer type, build an rvalue for the given address.
@end deffn
@geindex gcc_jit_context_null (C function)
-@anchor{topics/expressions gcc_jit_context_null}@anchor{89}
+@anchor{topics/expressions gcc_jit_context_null}@anchor{8e}
@deffn {C Function} gcc_jit_rvalue *gcc_jit_context_null (gcc_jit_context@w{ }*ctxt, gcc_jit_type@w{ }*pointer_type)
Given a pointer type, build an rvalue for @code{NULL}. Essentially this
@@ -6221,7 +6322,7 @@ gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL)
@end deffn
@geindex gcc_jit_context_new_string_literal (C function)
-@anchor{topics/expressions gcc_jit_context_new_string_literal}@anchor{8a}
+@anchor{topics/expressions gcc_jit_context_new_string_literal}@anchor{8f}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_string_literal (gcc_jit_context@w{ }*ctxt, const char@w{ }*value)
Generate an rvalue for the given NIL-terminated string, of type
@@ -6229,19 +6330,19 @@ Generate an rvalue for the given NIL-terminated string, of type
@end deffn
@node Unary Operations,Binary Operations,Simple expressions,Rvalues
-@anchor{topics/expressions unary-operations}@anchor{8b}
+@anchor{topics/expressions unary-operations}@anchor{90}
@subsubsection Unary Operations
@geindex gcc_jit_context_new_unary_op (C function)
-@anchor{topics/expressions gcc_jit_context_new_unary_op}@anchor{8c}
+@anchor{topics/expressions gcc_jit_context_new_unary_op}@anchor{91}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_unary_op (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, enum gcc_jit_unary_op@w{ }op, gcc_jit_type@w{ }*result_type, gcc_jit_rvalue@w{ }*rvalue)
Build a unary operation out of an input rvalue.
@end deffn
@geindex gcc_jit_unary_op (C type)
-@anchor{topics/expressions gcc_jit_unary_op}@anchor{8d}
+@anchor{topics/expressions gcc_jit_unary_op}@anchor{92}
@deffn {C Type} enum gcc_jit_unary_op
@end deffn
@@ -6259,7 +6360,7 @@ C equivalent
@item
-@pxref{8e,,GCC_JIT_UNARY_OP_MINUS}
+@pxref{93,,GCC_JIT_UNARY_OP_MINUS}
@tab
@@ -6267,7 +6368,7 @@ C equivalent
@item
-@pxref{8f,,GCC_JIT_UNARY_OP_BITWISE_NEGATE}
+@pxref{94,,GCC_JIT_UNARY_OP_BITWISE_NEGATE}
@tab
@@ -6275,7 +6376,7 @@ C equivalent
@item
-@pxref{90,,GCC_JIT_UNARY_OP_LOGICAL_NEGATE}
+@pxref{95,,GCC_JIT_UNARY_OP_LOGICAL_NEGATE}
@tab
@@ -6283,7 +6384,7 @@ C equivalent
@item
-@pxref{91,,GCC_JIT_UNARY_OP_ABS}
+@pxref{96,,GCC_JIT_UNARY_OP_ABS}
@tab
@@ -6293,7 +6394,7 @@ C equivalent
@geindex GCC_JIT_UNARY_OP_MINUS (C macro)
-@anchor{topics/expressions GCC_JIT_UNARY_OP_MINUS}@anchor{8e}
+@anchor{topics/expressions GCC_JIT_UNARY_OP_MINUS}@anchor{93}
@deffn {C Macro} GCC_JIT_UNARY_OP_MINUS
Negate an arithmetic value; analogous to:
@@ -6308,7 +6409,7 @@ in C.
@end deffn
@geindex GCC_JIT_UNARY_OP_BITWISE_NEGATE (C macro)
-@anchor{topics/expressions GCC_JIT_UNARY_OP_BITWISE_NEGATE}@anchor{8f}
+@anchor{topics/expressions GCC_JIT_UNARY_OP_BITWISE_NEGATE}@anchor{94}
@deffn {C Macro} GCC_JIT_UNARY_OP_BITWISE_NEGATE
Bitwise negation of an integer value (one's complement); analogous
@@ -6324,7 +6425,7 @@ in C.
@end deffn
@geindex GCC_JIT_UNARY_OP_LOGICAL_NEGATE (C macro)
-@anchor{topics/expressions GCC_JIT_UNARY_OP_LOGICAL_NEGATE}@anchor{90}
+@anchor{topics/expressions GCC_JIT_UNARY_OP_LOGICAL_NEGATE}@anchor{95}
@deffn {C Macro} GCC_JIT_UNARY_OP_LOGICAL_NEGATE
Logical negation of an arithmetic or pointer value; analogous to:
@@ -6339,7 +6440,7 @@ in C.
@end deffn
@geindex GCC_JIT_UNARY_OP_ABS (C macro)
-@anchor{topics/expressions GCC_JIT_UNARY_OP_ABS}@anchor{91}
+@anchor{topics/expressions GCC_JIT_UNARY_OP_ABS}@anchor{96}
@deffn {C Macro} GCC_JIT_UNARY_OP_ABS
Absolute value of an arithmetic expression; analogous to:
@@ -6354,7 +6455,7 @@ in C.
@end deffn
@node Binary Operations,Comparisons,Unary Operations,Rvalues
-@anchor{topics/expressions binary-operations}@anchor{92}
+@anchor{topics/expressions binary-operations}@anchor{97}
@subsubsection Binary Operations
@@ -6366,7 +6467,7 @@ Build a binary operation out of two constituent rvalues.
@end deffn
@geindex gcc_jit_binary_op (C type)
-@anchor{topics/expressions gcc_jit_binary_op}@anchor{93}
+@anchor{topics/expressions gcc_jit_binary_op}@anchor{98}
@deffn {C Type} enum gcc_jit_binary_op
@end deffn
@@ -6384,7 +6485,7 @@ C equivalent
@item
-@pxref{94,,GCC_JIT_BINARY_OP_PLUS}
+@pxref{99,,GCC_JIT_BINARY_OP_PLUS}
@tab
@@ -6392,7 +6493,7 @@ C equivalent
@item
-@pxref{95,,GCC_JIT_BINARY_OP_MINUS}
+@pxref{9a,,GCC_JIT_BINARY_OP_MINUS}
@tab
@@ -6400,7 +6501,7 @@ C equivalent
@item
-@pxref{96,,GCC_JIT_BINARY_OP_MULT}
+@pxref{9b,,GCC_JIT_BINARY_OP_MULT}
@tab
@@ -6408,7 +6509,7 @@ C equivalent
@item
-@pxref{97,,GCC_JIT_BINARY_OP_DIVIDE}
+@pxref{9c,,GCC_JIT_BINARY_OP_DIVIDE}
@tab
@@ -6416,7 +6517,7 @@ C equivalent
@item
-@pxref{98,,GCC_JIT_BINARY_OP_MODULO}
+@pxref{9d,,GCC_JIT_BINARY_OP_MODULO}
@tab
@@ -6424,7 +6525,7 @@ C equivalent
@item
-@pxref{99,,GCC_JIT_BINARY_OP_BITWISE_AND}
+@pxref{9e,,GCC_JIT_BINARY_OP_BITWISE_AND}
@tab
@@ -6432,7 +6533,7 @@ C equivalent
@item
-@pxref{9a,,GCC_JIT_BINARY_OP_BITWISE_XOR}
+@pxref{9f,,GCC_JIT_BINARY_OP_BITWISE_XOR}
@tab
@@ -6440,7 +6541,7 @@ C equivalent
@item
-@pxref{9b,,GCC_JIT_BINARY_OP_BITWISE_OR}
+@pxref{a0,,GCC_JIT_BINARY_OP_BITWISE_OR}
@tab
@@ -6448,7 +6549,7 @@ C equivalent
@item
-@pxref{9c,,GCC_JIT_BINARY_OP_LOGICAL_AND}
+@pxref{a1,,GCC_JIT_BINARY_OP_LOGICAL_AND}
@tab
@@ -6456,7 +6557,7 @@ C equivalent
@item
-@pxref{9d,,GCC_JIT_BINARY_OP_LOGICAL_OR}
+@pxref{a2,,GCC_JIT_BINARY_OP_LOGICAL_OR}
@tab
@@ -6464,7 +6565,7 @@ C equivalent
@item
-@pxref{9e,,GCC_JIT_BINARY_OP_LSHIFT}
+@pxref{a3,,GCC_JIT_BINARY_OP_LSHIFT}
@tab
@@ -6472,7 +6573,7 @@ C equivalent
@item
-@pxref{9f,,GCC_JIT_BINARY_OP_RSHIFT}
+@pxref{a4,,GCC_JIT_BINARY_OP_RSHIFT}
@tab
@@ -6482,7 +6583,7 @@ C equivalent
@geindex GCC_JIT_BINARY_OP_PLUS (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_PLUS}@anchor{94}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_PLUS}@anchor{99}
@deffn {C Macro} GCC_JIT_BINARY_OP_PLUS
Addition of arithmetic values; analogous to:
@@ -6495,11 +6596,11 @@ Addition of arithmetic values; analogous to:
in C.
-For pointer addition, use @pxref{a0,,gcc_jit_context_new_array_access()}.
+For pointer addition, use @pxref{a5,,gcc_jit_context_new_array_access()}.
@end deffn
@geindex GCC_JIT_BINARY_OP_MINUS (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_MINUS}@anchor{95}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_MINUS}@anchor{9a}
@deffn {C Macro} GCC_JIT_BINARY_OP_MINUS
Subtraction of arithmetic values; analogous to:
@@ -6514,7 +6615,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_MULT (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_MULT}@anchor{96}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_MULT}@anchor{9b}
@deffn {C Macro} GCC_JIT_BINARY_OP_MULT
Multiplication of a pair of arithmetic values; analogous to:
@@ -6529,7 +6630,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_DIVIDE (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_DIVIDE}@anchor{97}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_DIVIDE}@anchor{9c}
@deffn {C Macro} GCC_JIT_BINARY_OP_DIVIDE
Quotient of division of arithmetic values; analogous to:
@@ -6548,7 +6649,7 @@ a floating-point result type indicates floating-point division.
@end deffn
@geindex GCC_JIT_BINARY_OP_MODULO (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_MODULO}@anchor{98}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_MODULO}@anchor{9d}
@deffn {C Macro} GCC_JIT_BINARY_OP_MODULO
Remainder of division of arithmetic values; analogous to:
@@ -6563,7 +6664,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_BITWISE_AND (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_AND}@anchor{99}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_AND}@anchor{9e}
@deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_AND
Bitwise AND; analogous to:
@@ -6578,7 +6679,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_BITWISE_XOR (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_XOR}@anchor{9a}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_XOR}@anchor{9f}
@deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_XOR
Bitwise exclusive OR; analogous to:
@@ -6593,7 +6694,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_BITWISE_OR (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_OR}@anchor{9b}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_BITWISE_OR}@anchor{a0}
@deffn {C Macro} GCC_JIT_BINARY_OP_BITWISE_OR
Bitwise inclusive OR; analogous to:
@@ -6608,7 +6709,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_LOGICAL_AND (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_LOGICAL_AND}@anchor{9c}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_LOGICAL_AND}@anchor{a1}
@deffn {C Macro} GCC_JIT_BINARY_OP_LOGICAL_AND
Logical AND; analogous to:
@@ -6623,7 +6724,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_LOGICAL_OR (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_LOGICAL_OR}@anchor{9d}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_LOGICAL_OR}@anchor{a2}
@deffn {C Macro} GCC_JIT_BINARY_OP_LOGICAL_OR
Logical OR; analogous to:
@@ -6638,7 +6739,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_LSHIFT (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_LSHIFT}@anchor{9e}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_LSHIFT}@anchor{a3}
@deffn {C Macro} GCC_JIT_BINARY_OP_LSHIFT
Left shift; analogous to:
@@ -6653,7 +6754,7 @@ in C.
@end deffn
@geindex GCC_JIT_BINARY_OP_RSHIFT (C macro)
-@anchor{topics/expressions GCC_JIT_BINARY_OP_RSHIFT}@anchor{9f}
+@anchor{topics/expressions GCC_JIT_BINARY_OP_RSHIFT}@anchor{a4}
@deffn {C Macro} GCC_JIT_BINARY_OP_RSHIFT
Right shift; analogous to:
@@ -6668,7 +6769,7 @@ in C.
@end deffn
@node Comparisons,Function calls,Binary Operations,Rvalues
-@anchor{topics/expressions comparisons}@anchor{a1}
+@anchor{topics/expressions comparisons}@anchor{a6}
@subsubsection Comparisons
@@ -6680,7 +6781,7 @@ Build a boolean rvalue out of the comparison of two other rvalues.
@end deffn
@geindex gcc_jit_comparison (C type)
-@anchor{topics/expressions gcc_jit_comparison}@anchor{a2}
+@anchor{topics/expressions gcc_jit_comparison}@anchor{a7}
@deffn {C Type} enum gcc_jit_comparison
@end deffn
@@ -6746,12 +6847,12 @@ C equivalent
@node Function calls,Type-coercion,Comparisons,Rvalues
-@anchor{topics/expressions function-calls}@anchor{a3}
+@anchor{topics/expressions function-calls}@anchor{a8}
@subsubsection Function calls
@geindex gcc_jit_context_new_call (C function)
-@anchor{topics/expressions gcc_jit_context_new_call}@anchor{a4}
+@anchor{topics/expressions gcc_jit_context_new_call}@anchor{a9}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_call (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_function@w{ }*func, int@w{ }numargs, gcc_jit_rvalue@w{ }**args)
Given a function and the given table of argument rvalues, construct a
@@ -6759,7 +6860,7 @@ call to the function, with the result as an rvalue.
@cartouche
@quotation Note
-@pxref{a4,,gcc_jit_context_new_call()} merely builds a
+@pxref{a9,,gcc_jit_context_new_call()} merely builds a
@pxref{13,,gcc_jit_rvalue} i.e. an expression that can be evaluated,
perhaps as part of a more complicated expression.
The call @emph{won't} happen unless you add a statement to a function
@@ -6767,7 +6868,7 @@ that evaluates the expression.
For example, if you want to call a function and discard the result
(or to call a function with @code{void} return type), use
-@pxref{a5,,gcc_jit_block_add_eval()}:
+@pxref{aa,,gcc_jit_block_add_eval()}:
@example
/* Add "(void)printf (arg0, arg1);". */
@@ -6786,12 +6887,12 @@ gcc_jit_block_add_eval (
@end deffn
@node Type-coercion,,Function calls,Rvalues
-@anchor{topics/expressions type-coercion}@anchor{a6}
+@anchor{topics/expressions type-coercion}@anchor{ab}
@subsubsection Type-coercion
@geindex gcc_jit_context_new_cast (C function)
-@anchor{topics/expressions gcc_jit_context_new_cast}@anchor{a7}
+@anchor{topics/expressions gcc_jit_context_new_cast}@anchor{ac}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_context_new_cast (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue, gcc_jit_type@w{ }*type)
Given an rvalue of T, construct another rvalue of another type.
@@ -6816,7 +6917,7 @@ P* <-> Q*, for pointer types P and Q
@end deffn
@node Lvalues,Working with pointers structs and unions,Rvalues,Expressions
-@anchor{topics/expressions lvalues}@anchor{a8}
+@anchor{topics/expressions lvalues}@anchor{ad}
@subsection Lvalues
@@ -6830,21 +6931,21 @@ a storage area (such as a variable). It is also usable as an rvalue,
where the rvalue is computed by reading from the storage area.
@geindex gcc_jit_lvalue_as_object (C function)
-@anchor{topics/expressions gcc_jit_lvalue_as_object}@anchor{a9}
+@anchor{topics/expressions gcc_jit_lvalue_as_object}@anchor{ae}
@deffn {C Function} gcc_jit_object * gcc_jit_lvalue_as_object (gcc_jit_lvalue@w{ }*lvalue)
Upcast an lvalue to be an object.
@end deffn
@geindex gcc_jit_lvalue_as_rvalue (C function)
-@anchor{topics/expressions gcc_jit_lvalue_as_rvalue}@anchor{aa}
+@anchor{topics/expressions gcc_jit_lvalue_as_rvalue}@anchor{af}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_lvalue_as_rvalue (gcc_jit_lvalue@w{ }*lvalue)
Upcast an lvalue to be an rvalue.
@end deffn
@geindex gcc_jit_lvalue_get_address (C function)
-@anchor{topics/expressions gcc_jit_lvalue_get_address}@anchor{ab}
+@anchor{topics/expressions gcc_jit_lvalue_get_address}@anchor{b0}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_lvalue_get_address (gcc_jit_lvalue@w{ }*lvalue, gcc_jit_location@w{ }*loc)
Take the address of an lvalue; analogous to:
@@ -6864,12 +6965,12 @@ in C.
@end menu
@node Global variables,,,Lvalues
-@anchor{topics/expressions global-variables}@anchor{ac}
+@anchor{topics/expressions global-variables}@anchor{b1}
@subsubsection Global variables
@geindex gcc_jit_context_new_global (C function)
-@anchor{topics/expressions gcc_jit_context_new_global}@anchor{ad}
+@anchor{topics/expressions gcc_jit_context_new_global}@anchor{b2}
@deffn {C Function} gcc_jit_lvalue * gcc_jit_context_new_global (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, enum gcc_jit_global_kind@w{ }kind, gcc_jit_type@w{ }*type, const char@w{ }*name)
Add a new global variable of the given type and name to the context.
@@ -6878,22 +6979,22 @@ The "kind" parameter determines the visibility of the "global" outside
of the @pxref{16,,gcc_jit_result}:
@geindex gcc_jit_global_kind (C type)
-@anchor{topics/expressions gcc_jit_global_kind}@anchor{ae}
+@anchor{topics/expressions gcc_jit_global_kind}@anchor{b3}
@deffn {C Type} enum gcc_jit_global_kind
@end deffn
@geindex GCC_JIT_GLOBAL_EXPORTED (C macro)
-@anchor{topics/expressions GCC_JIT_GLOBAL_EXPORTED}@anchor{af}
+@anchor{topics/expressions GCC_JIT_GLOBAL_EXPORTED}@anchor{b4}
@deffn {C Macro} GCC_JIT_GLOBAL_EXPORTED
Global is defined by the client code and is visible
by name outside of this JIT context via
-@pxref{b0,,gcc_jit_result_get_global()} (and this value is required for
+@pxref{b5,,gcc_jit_result_get_global()} (and this value is required for
the global to be accessible via that entrypoint).
@end deffn
@geindex GCC_JIT_GLOBAL_INTERNAL (C macro)
-@anchor{topics/expressions GCC_JIT_GLOBAL_INTERNAL}@anchor{b1}
+@anchor{topics/expressions GCC_JIT_GLOBAL_INTERNAL}@anchor{b6}
@deffn {C Macro} GCC_JIT_GLOBAL_INTERNAL
Global is defined by the client code, but is invisible
@@ -6903,7 +7004,7 @@ context and within child contexts.
@end deffn
@geindex GCC_JIT_GLOBAL_IMPORTED (C macro)
-@anchor{topics/expressions GCC_JIT_GLOBAL_IMPORTED}@anchor{b2}
+@anchor{topics/expressions GCC_JIT_GLOBAL_IMPORTED}@anchor{b7}
@deffn {C Macro} GCC_JIT_GLOBAL_IMPORTED
Global is not defined by the client code; we're merely
@@ -6913,12 +7014,12 @@ header file.
@end deffn
@node Working with pointers structs and unions,,Lvalues,Expressions
-@anchor{topics/expressions working-with-pointers-structs-and-unions}@anchor{b3}
+@anchor{topics/expressions working-with-pointers-structs-and-unions}@anchor{b8}
@subsection Working with pointers, structs and unions
@geindex gcc_jit_rvalue_dereference (C function)
-@anchor{topics/expressions gcc_jit_rvalue_dereference}@anchor{b4}
+@anchor{topics/expressions gcc_jit_rvalue_dereference}@anchor{b9}
@deffn {C Function} gcc_jit_lvalue * gcc_jit_rvalue_dereference (gcc_jit_rvalue@w{ }*rvalue, gcc_jit_location@w{ }*loc)
Given an rvalue of pointer type @code{T *}, dereferencing the pointer,
@@ -6936,7 +7037,7 @@ in C.
Field access is provided separately for both lvalues and rvalues.
@geindex gcc_jit_lvalue_access_field (C function)
-@anchor{topics/expressions gcc_jit_lvalue_access_field}@anchor{b5}
+@anchor{topics/expressions gcc_jit_lvalue_access_field}@anchor{ba}
@deffn {C Function} gcc_jit_lvalue * gcc_jit_lvalue_access_field (gcc_jit_lvalue@w{ }*struct_, gcc_jit_location@w{ }*loc, gcc_jit_field@w{ }*field)
Given an lvalue of struct or union type, access the given field,
@@ -6952,7 +7053,7 @@ in C.
@end deffn
@geindex gcc_jit_rvalue_access_field (C function)
-@anchor{topics/expressions gcc_jit_rvalue_access_field}@anchor{b6}
+@anchor{topics/expressions gcc_jit_rvalue_access_field}@anchor{bb}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_rvalue_access_field (gcc_jit_rvalue@w{ }*struct_, gcc_jit_location@w{ }*loc, gcc_jit_field@w{ }*field)
Given an rvalue of struct or union type, access the given field
@@ -6968,7 +7069,7 @@ in C.
@end deffn
@geindex gcc_jit_rvalue_dereference_field (C function)
-@anchor{topics/expressions gcc_jit_rvalue_dereference_field}@anchor{b7}
+@anchor{topics/expressions gcc_jit_rvalue_dereference_field}@anchor{bc}
@deffn {C Function} gcc_jit_lvalue * gcc_jit_rvalue_dereference_field (gcc_jit_rvalue@w{ }*ptr, gcc_jit_location@w{ }*loc, gcc_jit_field@w{ }*field)
Given an rvalue of pointer type @code{T *} where T is of struct or union
@@ -6984,7 +7085,7 @@ in C, itself equivalent to @code{(*EXPR).FIELD}.
@end deffn
@geindex gcc_jit_context_new_array_access (C function)
-@anchor{topics/expressions gcc_jit_context_new_array_access}@anchor{a0}
+@anchor{topics/expressions gcc_jit_context_new_array_access}@anchor{a5}
@deffn {C Function} gcc_jit_lvalue * gcc_jit_context_new_array_access (gcc_jit_context@w{ }*ctxt, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*ptr, gcc_jit_rvalue@w{ }*index)
Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at
@@ -7019,7 +7120,7 @@ in C (or, indeed, to @code{PTR + INDEX}).
@c <http://www.gnu.org/licenses/>.
@node Creating and using functions,Source Locations,Expressions,Topic Reference
-@anchor{topics/functions doc}@anchor{b8}@anchor{topics/functions creating-and-using-functions}@anchor{b9}
+@anchor{topics/functions doc}@anchor{bd}@anchor{topics/functions creating-and-using-functions}@anchor{be}
@section Creating and using functions
@@ -7032,7 +7133,7 @@ in C (or, indeed, to @code{PTR + INDEX}).
@end menu
@node Params,Functions,,Creating and using functions
-@anchor{topics/functions params}@anchor{ba}
+@anchor{topics/functions params}@anchor{bf}
@subsection Params
@@ -7055,28 +7156,28 @@ Parameters are lvalues, and thus are also rvalues (and objects), so the
following upcasts are available:
@geindex gcc_jit_param_as_lvalue (C function)
-@anchor{topics/functions gcc_jit_param_as_lvalue}@anchor{bb}
+@anchor{topics/functions gcc_jit_param_as_lvalue}@anchor{c0}
@deffn {C Function} gcc_jit_lvalue * gcc_jit_param_as_lvalue (gcc_jit_param@w{ }*param)
Upcasting from param to lvalue.
@end deffn
@geindex gcc_jit_param_as_rvalue (C function)
-@anchor{topics/functions gcc_jit_param_as_rvalue}@anchor{bc}
+@anchor{topics/functions gcc_jit_param_as_rvalue}@anchor{c1}
@deffn {C Function} gcc_jit_rvalue * gcc_jit_param_as_rvalue (gcc_jit_param@w{ }*param)
Upcasting from param to rvalue.
@end deffn
@geindex gcc_jit_param_as_object (C function)
-@anchor{topics/functions gcc_jit_param_as_object}@anchor{bd}
+@anchor{topics/functions gcc_jit_param_as_object}@anchor{c2}
@deffn {C Function} gcc_jit_object * gcc_jit_param_as_object (gcc_jit_param@w{ }*param)
Upcasting from param to object.
@end deffn
@node Functions,Blocks,Params,Creating and using functions
-@anchor{topics/functions functions}@anchor{be}
+@anchor{topics/functions functions}@anchor{c3}
@subsection Functions
@@ -7095,7 +7196,7 @@ creating ourselves, or one that we're referencing.
Create a gcc_jit_function with the given name and parameters.
@geindex gcc_jit_function_kind (C type)
-@anchor{topics/functions gcc_jit_function_kind}@anchor{bf}
+@anchor{topics/functions gcc_jit_function_kind}@anchor{c4}
@deffn {C Type} enum gcc_jit_function_kind
@end deffn
@@ -7105,7 +7206,7 @@ values:
@quotation
@geindex GCC_JIT_FUNCTION_EXPORTED (C macro)
-@anchor{topics/functions GCC_JIT_FUNCTION_EXPORTED}@anchor{c0}
+@anchor{topics/functions GCC_JIT_FUNCTION_EXPORTED}@anchor{c5}
@deffn {C Macro} GCC_JIT_FUNCTION_EXPORTED
Function is defined by the client code and visible
@@ -7117,7 +7218,7 @@ for this function from a @pxref{16,,gcc_jit_result} via
@end deffn
@geindex GCC_JIT_FUNCTION_INTERNAL (C macro)
-@anchor{topics/functions GCC_JIT_FUNCTION_INTERNAL}@anchor{c1}
+@anchor{topics/functions GCC_JIT_FUNCTION_INTERNAL}@anchor{c6}
@deffn {C Macro} GCC_JIT_FUNCTION_INTERNAL
Function is defined by the client code, but is invisible
@@ -7125,7 +7226,7 @@ outside of the JIT. Analogous to a "static" function.
@end deffn
@geindex GCC_JIT_FUNCTION_IMPORTED (C macro)
-@anchor{topics/functions GCC_JIT_FUNCTION_IMPORTED}@anchor{c2}
+@anchor{topics/functions GCC_JIT_FUNCTION_IMPORTED}@anchor{c7}
@deffn {C Macro} GCC_JIT_FUNCTION_IMPORTED
Function is not defined by the client code; we're merely
@@ -7134,7 +7235,7 @@ header file.
@end deffn
@geindex GCC_JIT_FUNCTION_ALWAYS_INLINE (C macro)
-@anchor{topics/functions GCC_JIT_FUNCTION_ALWAYS_INLINE}@anchor{c3}
+@anchor{topics/functions GCC_JIT_FUNCTION_ALWAYS_INLINE}@anchor{c8}
@deffn {C Macro} GCC_JIT_FUNCTION_ALWAYS_INLINE
Function is only ever inlined into other functions, and is
@@ -7151,19 +7252,19 @@ same as GCC_JIT_FUNCTION_INTERNAL.
@end deffn
@geindex gcc_jit_context_get_builtin_function (C function)
-@anchor{topics/functions gcc_jit_context_get_builtin_function}@anchor{c4}
+@anchor{topics/functions gcc_jit_context_get_builtin_function}@anchor{c9}
@deffn {C Function} gcc_jit_function *gcc_jit_context_get_builtin_function (gcc_jit_context@w{ }*ctxt, const char@w{ }*name)
@end deffn
@geindex gcc_jit_function_as_object (C function)
-@anchor{topics/functions gcc_jit_function_as_object}@anchor{c5}
+@anchor{topics/functions gcc_jit_function_as_object}@anchor{ca}
@deffn {C Function} gcc_jit_object * gcc_jit_function_as_object (gcc_jit_function@w{ }*func)
Upcasting from function to object.
@end deffn
@geindex gcc_jit_function_get_param (C function)
-@anchor{topics/functions gcc_jit_function_get_param}@anchor{c6}
+@anchor{topics/functions gcc_jit_function_get_param}@anchor{cb}
@deffn {C Function} gcc_jit_param * gcc_jit_function_get_param (gcc_jit_function@w{ }*func, int@w{ }index)
Get the param of the given index (0-based).
@@ -7185,7 +7286,7 @@ name.
@end deffn
@node Blocks,Statements,Functions,Creating and using functions
-@anchor{topics/functions blocks}@anchor{c7}
+@anchor{topics/functions blocks}@anchor{cc}
@subsection Blocks
@@ -7201,14 +7302,15 @@ The first basic block that you create within a function will
be the entrypoint.
Each basic block that you create within a function must be
-terminated, either with a conditional, a jump, or a return.
+terminated, either with a conditional, a jump, a return, or a
+switch.
It's legal to have multiple basic blocks that return within
one function.
@end deffn
@geindex gcc_jit_function_new_block (C function)
-@anchor{topics/functions gcc_jit_function_new_block}@anchor{c8}
+@anchor{topics/functions gcc_jit_function_new_block}@anchor{cd}
@deffn {C Function} gcc_jit_block * gcc_jit_function_new_block (gcc_jit_function@w{ }*func, const char@w{ }*name)
Create a basic block of the given name. The name may be NULL, but
@@ -7218,26 +7320,26 @@ messages.
@end deffn
@geindex gcc_jit_block_as_object (C function)
-@anchor{topics/functions gcc_jit_block_as_object}@anchor{c9}
+@anchor{topics/functions gcc_jit_block_as_object}@anchor{ce}
@deffn {C Function} gcc_jit_object * gcc_jit_block_as_object (gcc_jit_block@w{ }*block)
Upcast from block to object.
@end deffn
@geindex gcc_jit_block_get_function (C function)
-@anchor{topics/functions gcc_jit_block_get_function}@anchor{ca}
+@anchor{topics/functions gcc_jit_block_get_function}@anchor{cf}
@deffn {C Function} gcc_jit_function * gcc_jit_block_get_function (gcc_jit_block@w{ }*block)
Which function is this block within?
@end deffn
@node Statements,,Blocks,Creating and using functions
-@anchor{topics/functions statements}@anchor{cb}
+@anchor{topics/functions statements}@anchor{d0}
@subsection Statements
@geindex gcc_jit_block_add_eval (C function)
-@anchor{topics/functions gcc_jit_block_add_eval}@anchor{a5}
+@anchor{topics/functions gcc_jit_block_add_eval}@anchor{aa}
@deffn {C Function} void gcc_jit_block_add_eval (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue)
Add evaluation of an rvalue, discarding the result
@@ -7333,7 +7435,7 @@ block, boolval, on_true, and on_false must be non-NULL.
@end deffn
@geindex gcc_jit_block_end_with_jump (C function)
-@anchor{topics/functions gcc_jit_block_end_with_jump}@anchor{cc}
+@anchor{topics/functions gcc_jit_block_end_with_jump}@anchor{d1}
@deffn {C Function} void gcc_jit_block_end_with_jump (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_block@w{ }*target)
Terminate a block by adding a jump to the given target block.
@@ -7348,7 +7450,7 @@ goto target;
@end deffn
@geindex gcc_jit_block_end_with_return (C function)
-@anchor{topics/functions gcc_jit_block_end_with_return}@anchor{cd}
+@anchor{topics/functions gcc_jit_block_end_with_return}@anchor{d2}
@deffn {C Function} void gcc_jit_block_end_with_return (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*rvalue)
Terminate a block by adding evaluation of an rvalue, returning the value.
@@ -7363,7 +7465,7 @@ return expression;
@end deffn
@geindex gcc_jit_block_end_with_void_return (C function)
-@anchor{topics/functions gcc_jit_block_end_with_void_return}@anchor{ce}
+@anchor{topics/functions gcc_jit_block_end_with_void_return}@anchor{d3}
@deffn {C Function} void gcc_jit_block_end_with_void_return (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc)
Terminate a block by adding a valueless return, for use within a function
@@ -7378,6 +7480,217 @@ return;
@noindent
@end deffn
+@geindex gcc_jit_block_end_with_switch (C function)
+@anchor{topics/functions gcc_jit_block_end_with_switch}@anchor{d4}
+@deffn {C Function} void gcc_jit_block_end_with_switch (gcc_jit_block@w{ }*block, gcc_jit_location@w{ }*loc, gcc_jit_rvalue@w{ }*expr, gcc_jit_block@w{ }*default_block, int@w{ }num_cases, gcc_jit_case@w{ }**cases)
+
+Terminate a block by adding evalation of an rvalue, then performing
+a multiway branch.
+
+This is roughly equivalent to this C code:
+
+@example
+switch (expr)
+ @{
+ default:
+ goto default_block;
+
+ case C0.min_value ... C0.max_value:
+ goto C0.dest_block;
+
+ case C1.min_value ... C1.max_value:
+ goto C1.dest_block;
+
+ ...etc...
+
+ case C[N - 1].min_value ... C[N - 1].max_value:
+ goto C[N - 1].dest_block;
+@}
+@end example
+
+@noindent
+
+@code{block}, @code{expr}, @code{default_block} and @code{cases} must all be
+non-NULL.
+
+@code{expr} must be of the same integer type as all of the @code{min_value}
+and @code{max_value} within the cases.
+
+@code{num_cases} must be >= 0.
+
+The ranges of the cases must not overlap (or have duplicate
+values).
+
+The API entrypoints relating to switch statements and cases:
+
+@quotation
+
+
+@itemize *
+
+@item
+@pxref{d4,,gcc_jit_block_end_with_switch()}
+
+@item
+@pxref{d5,,gcc_jit_case_as_object()}
+
+@item
+@pxref{d6,,gcc_jit_context_new_case()}
+@end itemize
+@end quotation
+
+were added in @pxref{d7,,LIBGCCJIT_ABI_3}; you can test for their presence
+using
+
+@example
+#ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
+@end example
+
+@noindent
+
+@geindex gcc_jit_case (C type)
+@anchor{topics/functions gcc_jit_case}@anchor{d8}
+@deffn {C Type} gcc_jit_case
+@end deffn
+
+A @cite{gcc_jit_case} represents a case within a switch statement, and
+is created within a particular @pxref{8,,gcc_jit_context} using
+@pxref{d6,,gcc_jit_context_new_case()}.
+
+Each case expresses a multivalued range of integer values. You
+can express single-valued cases by passing in the same value for
+both @cite{min_value} and @cite{max_value}.
+
+@geindex gcc_jit_context_new_case (C function)
+@anchor{topics/functions gcc_jit_context_new_case}@anchor{d6}
+@deffn {C Function} gcc_jit_case * gcc_jit_context_new_case (gcc_jit_context@w{ }*ctxt, gcc_jit_rvalue@w{ }*min_value, gcc_jit_rvalue@w{ }*max_value, gcc_jit_block@w{ }*dest_block)
+
+Create a new gcc_jit_case instance for use in a switch statement.
+@cite{min_value} and @cite{max_value} must be constants of an integer type,
+which must match that of the expression of the switch statement.
+
+@cite{dest_block} must be within the same function as the switch
+statement.
+@end deffn
+
+@geindex gcc_jit_case_as_object (C function)
+@anchor{topics/functions gcc_jit_case_as_object}@anchor{d5}
+@deffn {C Function} gcc_jit_object * gcc_jit_case_as_object (gcc_jit_case@w{ }*case_)
+
+Upcast from a case to an object.
+@end deffn
+
+Here's an example of creating a switch statement:
+
+@quotation
+
+@example
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+@{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ @{
+ switch (x)
+ @{
+ case 0 ... 5:
+ return 3;
+
+ case 25 ... 27:
+ return 4;
+
+ case -42 ... -17:
+ return 83;
+
+ case 40:
+ return 8;
+
+ default:
+ return 10;
+ @}
+ @}
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *return_type = t_int;
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (ctxt, NULL, t_int, "x");
+ gcc_jit_param *params[1] = @{x@};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ 1, params, 0);
+
+ gcc_jit_block *b_initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block *b_default =
+ gcc_jit_function_new_block (func, "default");
+ gcc_jit_block *b_case_0_5 =
+ gcc_jit_function_new_block (func, "case_0_5");
+ gcc_jit_block *b_case_25_27 =
+ gcc_jit_function_new_block (func, "case_25_27");
+ gcc_jit_block *b_case_m42_m17 =
+ gcc_jit_function_new_block (func, "case_m42_m17");
+ gcc_jit_block *b_case_40 =
+ gcc_jit_function_new_block (func, "case_40");
+
+ gcc_jit_case *cases[4] = @{
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 0),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 5),
+ b_case_0_5),
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 25),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 27),
+ b_case_25_27),
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -42),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -17),
+ b_case_m42_m17),
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40),
+ b_case_40)
+ @};
+ gcc_jit_block_end_with_switch (
+ b_initial, NULL,
+ gcc_jit_param_as_rvalue (x),
+ b_default,
+ 4, cases);
+
+ gcc_jit_block_end_with_return (
+ b_case_0_5, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3));
+ gcc_jit_block_end_with_return (
+ b_case_25_27, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 4));
+ gcc_jit_block_end_with_return (
+ b_case_m42_m17, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 83));
+ gcc_jit_block_end_with_return (
+ b_case_40, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 8));
+ gcc_jit_block_end_with_return (
+ b_default, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10));
+@}
+
+
+@end example
+
+@noindent
+@end quotation
+@end deffn
+
@c Copyright (C) 2014-2015 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -7396,7 +7709,7 @@ return;
@c <http://www.gnu.org/licenses/>.
@node Source Locations,Compiling a context,Creating and using functions,Topic Reference
-@anchor{topics/locations source-locations}@anchor{cf}@anchor{topics/locations doc}@anchor{d0}
+@anchor{topics/locations source-locations}@anchor{d9}@anchor{topics/locations doc}@anchor{da}
@section Source Locations
@@ -7442,7 +7755,7 @@ location.
@end menu
@node Faking it,,,Source Locations
-@anchor{topics/locations faking-it}@anchor{d1}
+@anchor{topics/locations faking-it}@anchor{db}
@subsection Faking it
@@ -7479,8 +7792,8 @@ file, giving you @emph{something} you can step through in the debugger.
@c along with this program. If not, see
@c <http://www.gnu.org/licenses/>.
-@node Compiling a context,,Source Locations,Topic Reference
-@anchor{topics/compilation compiling-a-context}@anchor{d2}@anchor{topics/compilation doc}@anchor{d3}
+@node Compiling a context,ABI and API compatibility,Source Locations,Topic Reference
+@anchor{topics/compilation compiling-a-context}@anchor{dc}@anchor{topics/compilation doc}@anchor{dd}
@section Compiling a context
@@ -7499,7 +7812,7 @@ prevent any future compilation of that context.
@end menu
@node In-memory compilation,Ahead-of-time compilation,,Compiling a context
-@anchor{topics/compilation in-memory-compilation}@anchor{d4}
+@anchor{topics/compilation in-memory-compilation}@anchor{de}
@subsection In-memory compilation
@@ -7534,7 +7847,7 @@ Functions are looked up by name. For this to succeed, a function
with a name matching @cite{funcname} must have been created on
@cite{result}'s context (or a parent context) via a call to
@pxref{11,,gcc_jit_context_new_function()} with @cite{kind}
-@pxref{c0,,GCC_JIT_FUNCTION_EXPORTED}:
+@pxref{c5,,GCC_JIT_FUNCTION_EXPORTED}:
@example
gcc_jit_context_new_function (ctxt,
@@ -7564,7 +7877,7 @@ to a segmentation fault.
@end deffn
@geindex gcc_jit_result_get_global (C function)
-@anchor{topics/compilation gcc_jit_result_get_global}@anchor{b0}
+@anchor{topics/compilation gcc_jit_result_get_global}@anchor{b5}
@deffn {C Function} void * gcc_jit_result_get_global (gcc_jit_result@w{ }*result, const char@w{ }*name)
Locate a given global within the built machine code.
@@ -7572,8 +7885,8 @@ Locate a given global within the built machine code.
Globals are looked up by name. For this to succeed, a global
with a name matching @cite{name} must have been created on
@cite{result}'s context (or a parent context) via a call to
-@pxref{ad,,gcc_jit_context_new_global()} with @cite{kind}
-@pxref{af,,GCC_JIT_GLOBAL_EXPORTED}.
+@pxref{b2,,gcc_jit_context_new_global()} with @cite{kind}
+@pxref{b4,,GCC_JIT_GLOBAL_EXPORTED}.
If the global is found, the result will need to be cast to a
pointer of the correct type before it can be called.
@@ -7621,11 +7934,11 @@ Once we're done with the code, this unloads the built .so file.
This cleans up the result; after calling this, it's no longer
valid to use the result, or any code or globals that were obtained
by calling @pxref{17,,gcc_jit_result_get_code()} or
-@pxref{b0,,gcc_jit_result_get_global()} on it.
+@pxref{b5,,gcc_jit_result_get_global()} on it.
@end deffn
@node Ahead-of-time compilation,,In-memory compilation,Compiling a context
-@anchor{topics/compilation ahead-of-time-compilation}@anchor{d5}
+@anchor{topics/compilation ahead-of-time-compilation}@anchor{df}
@subsection Ahead-of-time compilation
@@ -7654,7 +7967,7 @@ suffix of the output file when determining what to do.
@end cartouche
@geindex gcc_jit_output_kind (C type)
-@anchor{topics/compilation gcc_jit_output_kind}@anchor{d6}
+@anchor{topics/compilation gcc_jit_output_kind}@anchor{e0}
@deffn {C Type} enum gcc_jit_output_kind
@end deffn
@@ -7672,7 +7985,7 @@ Typical suffix
@item
-@pxref{d7,,GCC_JIT_OUTPUT_KIND_ASSEMBLER}
+@pxref{e1,,GCC_JIT_OUTPUT_KIND_ASSEMBLER}
@tab
@@ -7680,7 +7993,7 @@ Typical suffix
@item
-@pxref{d8,,GCC_JIT_OUTPUT_KIND_OBJECT_FILE}
+@pxref{e2,,GCC_JIT_OUTPUT_KIND_OBJECT_FILE}
@tab
@@ -7688,7 +8001,7 @@ Typical suffix
@item
-@pxref{d9,,GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}
+@pxref{e3,,GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}
@tab
@@ -7696,7 +8009,7 @@ Typical suffix
@item
-@pxref{da,,GCC_JIT_OUTPUT_KIND_EXECUTABLE}
+@pxref{e4,,GCC_JIT_OUTPUT_KIND_EXECUTABLE}
@tab
@@ -7706,21 +8019,21 @@ None, or .exe
@geindex GCC_JIT_OUTPUT_KIND_ASSEMBLER (C macro)
-@anchor{topics/compilation GCC_JIT_OUTPUT_KIND_ASSEMBLER}@anchor{d7}
+@anchor{topics/compilation GCC_JIT_OUTPUT_KIND_ASSEMBLER}@anchor{e1}
@deffn {C Macro} GCC_JIT_OUTPUT_KIND_ASSEMBLER
Compile the context to an assembler file.
@end deffn
@geindex GCC_JIT_OUTPUT_KIND_OBJECT_FILE (C macro)
-@anchor{topics/compilation GCC_JIT_OUTPUT_KIND_OBJECT_FILE}@anchor{d8}
+@anchor{topics/compilation GCC_JIT_OUTPUT_KIND_OBJECT_FILE}@anchor{e2}
@deffn {C Macro} GCC_JIT_OUTPUT_KIND_OBJECT_FILE
Compile the context to an object file.
@end deffn
@geindex GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY (C macro)
-@anchor{topics/compilation GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}@anchor{d9}
+@anchor{topics/compilation GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY}@anchor{e3}
@deffn {C Macro} GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY
Compile the context to a dynamic library.
@@ -7730,7 +8043,7 @@ against.
@end deffn
@geindex GCC_JIT_OUTPUT_KIND_EXECUTABLE (C macro)
-@anchor{topics/compilation GCC_JIT_OUTPUT_KIND_EXECUTABLE}@anchor{da}
+@anchor{topics/compilation GCC_JIT_OUTPUT_KIND_EXECUTABLE}@anchor{e4}
@deffn {C Macro} GCC_JIT_OUTPUT_KIND_EXECUTABLE
Compile the context to an executable.
@@ -7739,6 +8052,159 @@ There is currently no support for specifying libraries to link
against.
@end deffn
+@c Copyright (C) 2015 Free Software Foundation, Inc.
+@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
+@c
+@c This is free software: you can redistribute it and/or modify it
+@c under the terms of the GNU General Public License as published by
+@c the Free Software Foundation, either version 3 of the License, or
+@c (at your option) any later version.
+@c
+@c This program is distributed in the hope that it will be useful, but
+@c WITHOUT ANY WARRANTY; without even the implied warranty of
+@c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+@c General Public License for more details.
+@c
+@c You should have received a copy of the GNU General Public License
+@c along with this program. If not, see
+@c <http://www.gnu.org/licenses/>.
+
+@node ABI and API compatibility,,Compiling a context,Topic Reference
+@anchor{topics/compatibility abi-and-api-compatibility}@anchor{e5}@anchor{topics/compatibility doc}@anchor{e6}
+@section ABI and API compatibility
+
+
+The libgccjit developers strive for ABI and API backward-compatibility:
+programs built against libgccjit.so stand a good chance of running
+without recompilation against newer versions of libgccjit.so, and
+ought to recompile without modification against newer versions of
+libgccjit.h.
+
+@cartouche
+@quotation Note
+The libgccjit++.h C++ API is more experimental, and less
+locked-down at this time.
+@end quotation
+@end cartouche
+
+API compatibility is achieved by extending the API rather than changing
+it. For ABI compatiblity, we avoid bumping the SONAME, and instead use
+symbol versioning to tag each symbol, so that a binary linked against
+libgccjit.so is tagged according to the symbols that it uses.
+
+For example, @pxref{70,,gcc_jit_context_add_command_line_option()} was added in
+@code{LIBGCCJIT_ABI_1}. If a client program uses it, this can be detected
+from metadata by using @code{objdump}:
+
+@example
+$ objdump -p testsuite/jit/test-extra-options.c.exe | tail -n 8
+
+Version References:
+ required from libgccjit.so.0:
+ 0x00824161 0x00 04 LIBGCCJIT_ABI_1
+ 0x00824160 0x00 03 LIBGCCJIT_ABI_0
+ required from libc.so.6:
+@end example
+
+@noindent
+
+You can see the symbol tags provided by libgccjit.so using @code{objdump}:
+
+@example
+$ objdump -p libgccjit.so | less
+[...snip...]
+Version definitions:
+1 0x01 0x0ff81f20 libgccjit.so.0
+2 0x00 0x00824160 LIBGCCJIT_ABI_0
+3 0x00 0x00824161 LIBGCCJIT_ABI_1
+ LIBGCCJIT_ABI_0
+[...snip...]
+@end example
+
+@noindent
+
+@menu
+* ABI symbol tags::
+
+ABI symbol tags
+
+* LIBGCCJIT_ABI_0::
+* LIBGCCJIT_ABI_1::
+* LIBGCCJIT_ABI_2::
+* LIBGCCJIT_ABI_3::
+
+@end menu
+
+
+@node ABI symbol tags,,,ABI and API compatibility
+@anchor{topics/compatibility abi-symbol-tags}@anchor{e7}
+@subsection ABI symbol tags
+
+
+The initial release of libgccjit (in gcc 5.1) did not use symbol versioning.
+
+Newer releases use the following tags.
+
+@menu
+* LIBGCCJIT_ABI_0::
+* LIBGCCJIT_ABI_1::
+* LIBGCCJIT_ABI_2::
+* LIBGCCJIT_ABI_3::
+
+@end menu
+
+@node LIBGCCJIT_ABI_0,LIBGCCJIT_ABI_1,,ABI symbol tags
+@anchor{topics/compatibility libgccjit-abi-0}@anchor{e8}@anchor{topics/compatibility id1}@anchor{e9}
+@subsubsection @code{LIBGCCJIT_ABI_0}
+
+
+All entrypoints in the initial release of libgccjit are tagged with
+@code{LIBGCCJIT_ABI_0}, to signify the transition to symbol versioning.
+
+Binaries built against older copies of @code{libgccjit.so} should
+continue to work, with this being handled transparently by the linker
+(see this post@footnote{https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02126.html})
+
+@node LIBGCCJIT_ABI_1,LIBGCCJIT_ABI_2,LIBGCCJIT_ABI_0,ABI symbol tags
+@anchor{topics/compatibility libgccjit-abi-1}@anchor{71}@anchor{topics/compatibility id2}@anchor{ea}
+@subsubsection @code{LIBGCCJIT_ABI_1}
+
+
+@code{LIBGCCJIT_ABI_1} covers the addition of
+@pxref{70,,gcc_jit_context_add_command_line_option()}
+
+@node LIBGCCJIT_ABI_2,LIBGCCJIT_ABI_3,LIBGCCJIT_ABI_1,ABI symbol tags
+@anchor{topics/compatibility libgccjit-abi-2}@anchor{6c}@anchor{topics/compatibility id3}@anchor{eb}
+@subsubsection @code{LIBGCCJIT_ABI_2}
+
+
+@code{LIBGCCJIT_ABI_2} covers the addition of
+@pxref{6b,,gcc_jit_context_set_bool_allow_unreachable_blocks()}
+
+@node LIBGCCJIT_ABI_3,,LIBGCCJIT_ABI_2,ABI symbol tags
+@anchor{topics/compatibility libgccjit-abi-3}@anchor{d7}@anchor{topics/compatibility id4}@anchor{ec}
+@subsubsection @code{LIBGCCJIT_ABI_3}
+
+
+@code{LIBGCCJIT_ABI_3} covers the addition of switch statements via API
+entrypoints:
+
+@quotation
+
+
+@itemize *
+
+@item
+@pxref{d4,,gcc_jit_block_end_with_switch()}
+
+@item
+@pxref{d5,,gcc_jit_case_as_object()}
+
+@item
+@pxref{d6,,gcc_jit_context_new_case()}
+@end itemize
+@end quotation
+
@c Copyright (C) 2014-2015 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -7757,7 +8223,7 @@ against.
@c <http://www.gnu.org/licenses/>.
@node C++ bindings for libgccjit,Internals,Topic Reference,Top
-@anchor{cp/index c-bindings-for-libgccjit}@anchor{db}@anchor{cp/index doc}@anchor{dc}
+@anchor{cp/index c-bindings-for-libgccjit}@anchor{ed}@anchor{cp/index doc}@anchor{ee}
@chapter C++ bindings for libgccjit
@@ -7858,6 +8324,7 @@ Options
* String Options: String Options<2>.
* Boolean options: Boolean options<2>.
* Integer options: Integer options<2>.
+* Additional command-line options: Additional command-line options<2>.
Types
@@ -7904,7 +8371,7 @@ Compiling a context
@node Tutorial<2>,Topic Reference<2>,,C++ bindings for libgccjit
-@anchor{cp/intro/index doc}@anchor{dd}@anchor{cp/intro/index tutorial}@anchor{de}
+@anchor{cp/intro/index doc}@anchor{ef}@anchor{cp/intro/index tutorial}@anchor{f0}
@section Tutorial
@@ -7934,7 +8401,7 @@ Compiling a context
@end menu
@node Tutorial part 1 "Hello world"<2>,Tutorial part 2 Creating a trivial machine code function<2>,,Tutorial<2>
-@anchor{cp/intro/tutorial01 doc}@anchor{df}@anchor{cp/intro/tutorial01 tutorial-part-1-hello-world}@anchor{e0}
+@anchor{cp/intro/tutorial01 doc}@anchor{f1}@anchor{cp/intro/tutorial01 tutorial-part-1-hello-world}@anchor{f2}
@subsection Tutorial part 1: "Hello world"
@@ -8104,7 +8571,7 @@ hello world
@c <http://www.gnu.org/licenses/>.
@node Tutorial part 2 Creating a trivial machine code function<2>,Tutorial part 3 Loops and variables<2>,Tutorial part 1 "Hello world"<2>,Tutorial<2>
-@anchor{cp/intro/tutorial02 doc}@anchor{e1}@anchor{cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{e2}
+@anchor{cp/intro/tutorial02 doc}@anchor{f3}@anchor{cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function}@anchor{f4}
@subsection Tutorial part 2: Creating a trivial machine code function
@@ -8133,7 +8600,7 @@ All state associated with compilation is associated with a
@code{gccjit::context}, which is a thin C++ wrapper around the C API's
@pxref{8,,gcc_jit_context *}.
-Create one using @pxref{e3,,gccjit;;context;;acquire()}:
+Create one using @pxref{f5,,gccjit;;context;;acquire()}:
@example
gccjit::context ctxt;
@@ -8146,7 +8613,7 @@ The JIT library has a system of types. It is statically-typed: every
expression is of a specific type, fixed at compile-time. In our example,
all of the expressions are of the C @cite{int} type, so let's obtain this from
the context, as a @code{gccjit::type}, using
-@pxref{e4,,gccjit;;context;;get_type()}:
+@pxref{f6,,gccjit;;context;;get_type()}:
@example
gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
@@ -8159,7 +8626,7 @@ entity in the API is associated with a @code{gccjit::context}.
Memory management is easy: all such "contextual" objects are automatically
cleaned up for you when the context is released, using
-@pxref{e5,,gccjit;;context;;release()}:
+@pxref{f7,,gccjit;;context;;release()}:
@example
ctxt.release ();
@@ -8192,7 +8659,7 @@ The C++ class hierarchy within the @code{gccjit} namespace looks like this:
One thing you can do with a @code{gccjit::object} is
to ask it for a human-readable description as a @code{std::string}, using
-@pxref{e6,,gccjit;;object;;get_debug_string()}:
+@pxref{f8,,gccjit;;object;;get_debug_string()}:
@example
printf ("obj: %s\n", obj.get_debug_string ().c_str ());
@@ -8212,7 +8679,7 @@ This is invaluable when debugging.
Let's create the function. To do so, we first need to construct
its single parameter, specifying its type and giving it a name,
-using @pxref{e7,,gccjit;;context;;new_param()}:
+using @pxref{f9,,gccjit;;context;;new_param()}:
@example
gccjit::param param_i = ctxt.new_param (int_type, "i");
@@ -8261,7 +8728,7 @@ gccjit::block block = func.new_block ();
Our basic block is relatively simple: it immediately terminates by
returning the value of an expression.
-We can build the expression using @pxref{e8,,gccjit;;context;;new_binary_op()}:
+We can build the expression using @pxref{fa,,gccjit;;context;;new_binary_op()}:
@example
gccjit::rvalue expr =
@@ -8274,7 +8741,7 @@ gccjit::rvalue expr =
A @code{gccjit::rvalue} is another example of a
@code{gccjit::object} subclass. As before, we can print it with
-@pxref{e6,,gccjit;;object;;get_debug_string()}.
+@pxref{f8,,gccjit;;object;;get_debug_string()}.
@example
printf ("expr: %s\n", expr.get_debug_string ().c_str ());
@@ -8311,7 +8778,7 @@ block.end_with_return (expr);
@noindent
OK, we've populated the context. We can now compile it using
-@pxref{e9,,gccjit;;context;;compile()}:
+@pxref{fb,,gccjit;;context;;compile()}:
@example
gcc_jit_result *result;
@@ -8361,12 +8828,12 @@ result: 25
@end menu
@node Options<3>,Full example<3>,,Tutorial part 2 Creating a trivial machine code function<2>
-@anchor{cp/intro/tutorial02 options}@anchor{ea}
+@anchor{cp/intro/tutorial02 options}@anchor{fc}
@subsubsection Options
To get more information on what's going on, you can set debugging flags
-on the context using @pxref{eb,,gccjit;;context;;set_bool_option()}.
+on the context using @pxref{fd,,gccjit;;context;;set_bool_option()}.
@c (I'm deliberately not mentioning
@c :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` here since I think
@@ -8438,7 +8905,7 @@ square:
By default, no optimizations are performed, the equivalent of GCC's
@cite{-O0} option. We can turn things up to e.g. @cite{-O3} by calling
-@pxref{ec,,gccjit;;context;;set_int_option()} with
+@pxref{fe,,gccjit;;context;;set_int_option()} with
@pxref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}:
@example
@@ -8472,7 +8939,7 @@ square:
Naturally this has only a small effect on such a trivial function.
@node Full example<3>,,Options<3>,Tutorial part 2 Creating a trivial machine code function<2>
-@anchor{cp/intro/tutorial02 full-example}@anchor{ed}
+@anchor{cp/intro/tutorial02 full-example}@anchor{ff}
@subsubsection Full example
@@ -8615,7 +9082,7 @@ result: 25
@c <http://www.gnu.org/licenses/>.
@node Tutorial part 3 Loops and variables<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,Tutorial part 2 Creating a trivial machine code function<2>,Tutorial<2>
-@anchor{cp/intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{ee}@anchor{cp/intro/tutorial03 doc}@anchor{ef}
+@anchor{cp/intro/tutorial03 tutorial-part-3-loops-and-variables}@anchor{100}@anchor{cp/intro/tutorial03 doc}@anchor{101}
@subsection Tutorial part 3: Loops and variables
@@ -8739,7 +9206,7 @@ gccjit::function func =
@end menu
@node Expressions lvalues and rvalues<2>,Control flow<2>,,Tutorial part 3 Loops and variables<2>
-@anchor{cp/intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{f0}
+@anchor{cp/intro/tutorial03 expressions-lvalues-and-rvalues}@anchor{102}
@subsubsection Expressions: lvalues and rvalues
@@ -8812,7 +9279,7 @@ body of a function.
Our new example has a new kind of expression: we have two local
variables. We create them by calling
-@pxref{f1,,gccjit;;function;;new_local()}, supplying a type and a name:
+@pxref{103,,gccjit;;function;;new_local()}, supplying a type and a name:
@example
/* Build locals: */
@@ -8838,7 +9305,7 @@ Instead, having added the local to the function, we have to separately add
an assignment of @cite{0} to @cite{local_i} at the beginning of the function.
@node Control flow<2>,Visualizing the control flow graph<2>,Expressions lvalues and rvalues<2>,Tutorial part 3 Loops and variables<2>
-@anchor{cp/intro/tutorial03 control-flow}@anchor{f2}
+@anchor{cp/intro/tutorial03 control-flow}@anchor{104}
@subsubsection Control flow
@@ -8877,8 +9344,8 @@ We now populate each block with statements.
The entry block @cite{b_initial} consists of initializations followed by a jump
to the conditional. We assign @cite{0} to @cite{i} and to @cite{sum}, using
-@pxref{f3,,gccjit;;block;;add_assignment()} to add
-an assignment statement, and using @pxref{f4,,gccjit;;context;;zero()} to get
+@pxref{105,,gccjit;;block;;add_assignment()} to add
+an assignment statement, and using @pxref{106,,gccjit;;context;;zero()} to get
the constant value @cite{0} for the relevant type for the right-hand side of
the assignment:
@@ -8905,7 +9372,7 @@ C example. It contains a single statement: a conditional, which jumps to
one of two destination blocks depending on a boolean
@code{gccjit::rvalue}, in this case the comparison of @cite{i} and @cite{n}.
-We could build the comparison using @pxref{f5,,gccjit;;context;;new_comparison()}:
+We could build the comparison using @pxref{107,,gccjit;;context;;new_comparison()}:
@example
gccjit::rvalue guard =
@@ -8916,7 +9383,7 @@ gccjit::rvalue guard =
@noindent
and can then use this to add @cite{b_loop_cond}'s sole statement, via
-@pxref{f6,,gccjit;;block;;end_with_conditional()}:
+@pxref{108,,gccjit;;block;;end_with_conditional()}:
@example
b_loop_cond.end_with_conditional (guard,
@@ -8950,7 +9417,7 @@ Next, we populate the body of the loop.
The C statement @cite{sum += i * i;} is an assignment operation, where an
lvalue is modified "in-place". We use
-@pxref{f7,,gccjit;;block;;add_assignment_op()} to handle these operations:
+@pxref{109,,gccjit;;block;;add_assignment_op()} to handle these operations:
@example
/* sum += i * i */
@@ -8978,7 +9445,7 @@ b_loop_body.add_assignment_op (i,
@cartouche
@quotation Note
For numeric constants other than 0 or 1, we could use
-@pxref{f8,,gccjit;;context;;new_rvalue()}, which has overloads
+@pxref{10a,,gccjit;;context;;new_rvalue()}, which has overloads
for both @code{int} and @code{double}.
@end quotation
@end cartouche
@@ -9054,12 +9521,12 @@ result: 285
@noindent
@node Visualizing the control flow graph<2>,Full example<4>,Control flow<2>,Tutorial part 3 Loops and variables<2>
-@anchor{cp/intro/tutorial03 visualizing-the-control-flow-graph}@anchor{f9}
+@anchor{cp/intro/tutorial03 visualizing-the-control-flow-graph}@anchor{10b}
@subsubsection Visualizing the control flow graph
You can see the control flow graph of a function using
-@pxref{fa,,gccjit;;function;;dump_to_dot()}:
+@pxref{10c,,gccjit;;function;;dump_to_dot()}:
@example
func.dump_to_dot ("/tmp/sum-of-squares.dot");
@@ -9093,7 +9560,7 @@ install it with @cite{yum install python-xdot}):
@end quotation
@node Full example<4>,,Visualizing the control flow graph<2>,Tutorial part 3 Loops and variables<2>
-@anchor{cp/intro/tutorial03 full-example}@anchor{fb}
+@anchor{cp/intro/tutorial03 full-example}@anchor{10d}
@subsubsection Full example
@@ -9276,7 +9743,7 @@ loop_test returned: 285
@c <http://www.gnu.org/licenses/>.
@node Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,,Tutorial part 3 Loops and variables<2>,Tutorial<2>
-@anchor{cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{fc}@anchor{cp/intro/tutorial04 doc}@anchor{fd}
+@anchor{cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter}@anchor{10e}@anchor{cp/intro/tutorial04 doc}@anchor{10f}
@subsection Tutorial part 4: Adding JIT-compilation to a toy interpreter
@@ -9298,7 +9765,7 @@ to it.
@end menu
@node Our toy interpreter<2>,Compiling to machine code<2>,,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 our-toy-interpreter}@anchor{fe}
+@anchor{cp/intro/tutorial04 our-toy-interpreter}@anchor{110}
@subsubsection Our toy interpreter
@@ -9706,7 +10173,7 @@ toyvm_function::interpret (int arg, FILE *trace)
@end quotation
@node Compiling to machine code<2>,Setting things up<2>,Our toy interpreter<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 compiling-to-machine-code}@anchor{ff}
+@anchor{cp/intro/tutorial04 compiling-to-machine-code}@anchor{111}
@subsubsection Compiling to machine code
@@ -9786,7 +10253,7 @@ This means our compiler has the following state:
@end quotation
@node Setting things up<2>,Populating the function<2>,Compiling to machine code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 setting-things-up}@anchor{100}
+@anchor{cp/intro/tutorial04 setting-things-up}@anchor{112}
@subsubsection Setting things up
@@ -9954,7 +10421,7 @@ We create the locals within the function.
@end quotation
@node Populating the function<2>,Verifying the control flow graph<2>,Setting things up<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 populating-the-function}@anchor{101}
+@anchor{cp/intro/tutorial04 populating-the-function}@anchor{113}
@subsubsection Populating the function
@@ -10082,7 +10549,7 @@ stack into @code{y} instead erroneously assigned it to @code{x}, leaving @code{y
uninitialized.
To track this kind of thing down, we can use
-@pxref{102,,gccjit;;block;;add_comment()} to add descriptive comments
+@pxref{114,,gccjit;;block;;add_comment()} to add descriptive comments
to the internal representation. This is invaluable when looking through
the generated IR for, say @code{factorial}:
@@ -10231,14 +10698,14 @@ to the next block.
This is analogous to simply incrementing the program counter.
@node Verifying the control flow graph<2>,Compiling the context<2>,Populating the function<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 verifying-the-control-flow-graph}@anchor{103}
+@anchor{cp/intro/tutorial04 verifying-the-control-flow-graph}@anchor{115}
@subsubsection Verifying the control flow graph
Having finished looping over the blocks, the context is complete.
As before, we can verify that the control flow and statements are sane by
-using @pxref{fa,,gccjit;;function;;dump_to_dot()}:
+using @pxref{10c,,gccjit;;function;;dump_to_dot()}:
@example
fn.dump_to_dot ("/tmp/factorial.dot");
@@ -10262,7 +10729,7 @@ errors in our compiler.
@end quotation
@node Compiling the context<2>,Single-stepping through the generated code<2>,Verifying the control flow graph<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 compiling-the-context}@anchor{104}
+@anchor{cp/intro/tutorial04 compiling-the-context}@anchor{116}
@subsubsection Compiling the context
@@ -10299,7 +10766,7 @@ We can now run the result:
@end quotation
@node Single-stepping through the generated code<2>,Examining the generated code<2>,Compiling the context<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 single-stepping-through-the-generated-code}@anchor{105}
+@anchor{cp/intro/tutorial04 single-stepping-through-the-generated-code}@anchor{117}
@subsubsection Single-stepping through the generated code
@@ -10313,14 +10780,14 @@ It's possible to debug the generated code. To do this we need to both:
@item
Set up source code locations for our statements, so that we can
meaningfully step through the code. We did this above by
-calling @pxref{106,,gccjit;;context;;new_location()} and using the
+calling @pxref{118,,gccjit;;context;;new_location()} and using the
results.
@item
Enable the generation of debugging information, by setting
@pxref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the
@code{gccjit::context} via
-@pxref{eb,,gccjit;;context;;set_bool_option()}:
+@pxref{fd,,gccjit;;context;;set_bool_option()}:
@example
ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
@@ -10392,14 +10859,14 @@ optimization level in a regular compiler.
@end cartouche
@node Examining the generated code<2>,Putting it all together<2>,Single-stepping through the generated code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 examining-the-generated-code}@anchor{107}
+@anchor{cp/intro/tutorial04 examining-the-generated-code}@anchor{119}
@subsubsection Examining the generated code
How good is the optimized code?
We can turn up optimizations, by calling
-@pxref{ec,,gccjit;;context;;set_int_option()} with
+@pxref{fe,,gccjit;;context;;set_int_option()} with
@pxref{1f,,GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL}:
@example
@@ -10581,7 +11048,7 @@ Note that the stack pushing and popping have been eliminated, as has the
recursive call (in favor of an iteration).
@node Putting it all together<2>,Behind the curtain How does our code get optimized?<2>,Examining the generated code<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 putting-it-all-together}@anchor{108}
+@anchor{cp/intro/tutorial04 putting-it-all-together}@anchor{11a}
@subsubsection Putting it all together
@@ -10614,7 +11081,7 @@ compiler result: 55
@noindent
@node Behind the curtain How does our code get optimized?<2>,,Putting it all together<2>,Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>
-@anchor{cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{109}
+@anchor{cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized}@anchor{11b}
@subsubsection Behind the curtain: How does our code get optimized?
@@ -10815,7 +11282,7 @@ representation: @code{initial}, @code{instr4} and @code{instr9}.
@end menu
@node Optimizing away stack manipulation<2>,Elimination of tail recursion<2>,,Behind the curtain How does our code get optimized?<2>
-@anchor{cp/intro/tutorial04 optimizing-away-stack-manipulation}@anchor{10a}
+@anchor{cp/intro/tutorial04 optimizing-away-stack-manipulation}@anchor{11c}
@subsubsection Optimizing away stack manipulation
@@ -11095,7 +11562,7 @@ instr9:
@noindent
@node Elimination of tail recursion<2>,,Optimizing away stack manipulation<2>,Behind the curtain How does our code get optimized?<2>
-@anchor{cp/intro/tutorial04 elimination-of-tail-recursion}@anchor{10b}
+@anchor{cp/intro/tutorial04 elimination-of-tail-recursion}@anchor{11d}
@subsubsection Elimination of tail recursion
@@ -11182,7 +11649,7 @@ instr9:
@c <http://www.gnu.org/licenses/>.
@node Topic Reference<2>,,Tutorial<2>,C++ bindings for libgccjit
-@anchor{cp/topics/index doc}@anchor{10c}@anchor{cp/topics/index topic-reference}@anchor{10d}
+@anchor{cp/topics/index doc}@anchor{11e}@anchor{cp/topics/index topic-reference}@anchor{11f}
@section Topic Reference
@@ -11225,6 +11692,7 @@ Options
* String Options: String Options<2>.
* Boolean options: Boolean options<2>.
* Integer options: Integer options<2>.
+* Additional command-line options: Additional command-line options<2>.
Types
@@ -11271,22 +11739,22 @@ Compiling a context
@node Compilation contexts<2>,Objects<2>,,Topic Reference<2>
-@anchor{cp/topics/contexts compilation-contexts}@anchor{10e}@anchor{cp/topics/contexts doc}@anchor{10f}
+@anchor{cp/topics/contexts compilation-contexts}@anchor{120}@anchor{cp/topics/contexts doc}@anchor{121}
@subsection Compilation contexts
@geindex gccjit;;context (C++ class)
-@anchor{cp/topics/contexts gccjit context}@anchor{110}
+@anchor{cp/topics/contexts gccjit context}@anchor{122}
@deffn {C++ Class} gccjit::context
@end deffn
-The top-level of the C++ API is the @pxref{110,,gccjit;;context} type.
+The top-level of the C++ API is the @pxref{122,,gccjit;;context} type.
-A @pxref{110,,gccjit;;context} instance encapsulates the state of a
+A @pxref{122,,gccjit;;context} instance encapsulates the state of a
compilation.
You can set up options on it, and add types, functions and code.
-Invoking @pxref{e9,,gccjit;;context;;compile()} on it gives you a
+Invoking @pxref{fb,,gccjit;;context;;compile()} on it gives you a
@pxref{16,,gcc_jit_result *}.
It is a thin wrapper around the C API's @pxref{8,,gcc_jit_context *}.
@@ -11301,7 +11769,7 @@ It is a thin wrapper around the C API's @pxref{8,,gcc_jit_context *}.
@end menu
@node Lifetime-management<2>,Thread-safety<2>,,Compilation contexts<2>
-@anchor{cp/topics/contexts lifetime-management}@anchor{111}
+@anchor{cp/topics/contexts lifetime-management}@anchor{123}
@subsubsection Lifetime-management
@@ -11310,16 +11778,16 @@ have their lifetime bounded by the context they are created within, and
cleanup of such objects is done for you when the context is released.
@geindex gccjit;;context;;acquire (C++ function)
-@anchor{cp/topics/contexts gccjit context acquire}@anchor{e3}
+@anchor{cp/topics/contexts gccjit context acquire}@anchor{f5}
@deffn {C++ Function} gccjit::context gccjit::context::acquire ()
-This function acquires a new @pxref{110,,gccjit;;context} instance,
+This function acquires a new @pxref{122,,gccjit;;context} instance,
which is independent of any others that may be present within this
process.
@end deffn
@geindex gccjit;;context;;release (C++ function)
-@anchor{cp/topics/contexts gccjit context release}@anchor{e5}
+@anchor{cp/topics/contexts gccjit context release}@anchor{f7}
@deffn {C++ Function} void gccjit::context::release ()
This function releases all resources associated with the given context.
@@ -11338,7 +11806,7 @@ ctxt.release ();
@end deffn
@geindex gccjit;;context;;new_child_context (C++ function)
-@anchor{cp/topics/contexts gccjit context new_child_context}@anchor{112}
+@anchor{cp/topics/contexts gccjit context new_child_context}@anchor{124}
@deffn {C++ Function} gccjit::context gccjit::context::new_child_context ()
Given an existing JIT context, create a child context.
@@ -11370,16 +11838,16 @@ there will likely be a performance hit for such nesting.
@end deffn
@node Thread-safety<2>,Error-handling<3>,Lifetime-management<2>,Compilation contexts<2>
-@anchor{cp/topics/contexts thread-safety}@anchor{113}
+@anchor{cp/topics/contexts thread-safety}@anchor{125}
@subsubsection Thread-safety
-Instances of @pxref{110,,gccjit;;context} created via
-@pxref{e3,,gccjit;;context;;acquire()} are independent from each other:
+Instances of @pxref{122,,gccjit;;context} created via
+@pxref{f5,,gccjit;;context;;acquire()} are independent from each other:
only one thread may use a given context at once, but multiple threads
could each have their own contexts without needing locks.
-Contexts created via @pxref{112,,gccjit;;context;;new_child_context()} are
+Contexts created via @pxref{124,,gccjit;;context;;new_child_context()} are
related to their parent context. They can be partitioned by their
ultimate ancestor into independent "family trees". Only one thread
within a process may use a given "family tree" of such contexts at once,
@@ -11387,7 +11855,7 @@ and if you're using multiple threads you should provide your own locking
around entire such context partitions.
@node Error-handling<3>,Debugging<2>,Thread-safety<2>,Compilation contexts<2>
-@anchor{cp/topics/contexts error-handling}@anchor{114}
+@anchor{cp/topics/contexts error-handling}@anchor{126}
@subsubsection Error-handling
@@ -11400,10 +11868,10 @@ NULL. You don't have to check everywhere for NULL results, since the
API gracefully handles a NULL being passed in for any argument.
Errors are printed on stderr and can be queried using
-@pxref{115,,gccjit;;context;;get_first_error()}.
+@pxref{127,,gccjit;;context;;get_first_error()}.
@geindex gccjit;;context;;get_first_error (C++ function)
-@anchor{cp/topics/contexts gccjit context get_first_error__gccjit contextP}@anchor{115}
+@anchor{cp/topics/contexts gccjit context get_first_error__gccjit contextP}@anchor{127}
@deffn {C++ Function} const char* gccjit::context::get_first_error (gccjit::context* ctxt)
Returns the first error message that occurred on the context.
@@ -11415,18 +11883,18 @@ If no errors occurred, this will be NULL.
@end deffn
@node Debugging<2>,Options<4>,Error-handling<3>,Compilation contexts<2>
-@anchor{cp/topics/contexts debugging}@anchor{116}
+@anchor{cp/topics/contexts debugging}@anchor{128}
@subsubsection Debugging
@geindex gccjit;;context;;dump_to_file (C++ function)
-@anchor{cp/topics/contexts gccjit context dump_to_file__ssCR i}@anchor{117}
+@anchor{cp/topics/contexts gccjit context dump_to_file__ssCR i}@anchor{129}
@deffn {C++ Function} void gccjit::context::dump_to_file (const std::string& path, int update_locations)
To help with debugging: dump a C-like representation to the given path,
describing what's been set up on the context.
-If "update_locations" is true, then also set up @pxref{118,,gccjit;;location}
+If "update_locations" is true, then also set up @pxref{12a,,gccjit;;location}
information throughout the context, pointing at the dump file as if it
were a source file. This may be of use in conjunction with
@code{GCCJIT::BOOL_OPTION_DEBUGINFO} to allow stepping through the
@@ -11434,7 +11902,7 @@ code in a debugger.
@end deffn
@geindex gccjit;;context;;dump_reproducer_to_file (C++ function)
-@anchor{cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP}@anchor{119}
+@anchor{cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP}@anchor{12b}
@deffn {C++ Function} void gccjit::context::dump_reproducer_to_file (gcc_jit_context* ctxt, const char* path)
This is a thin wrapper around the C API
@@ -11446,7 +11914,7 @@ for seeing what the C++ bindings are doing at the C level.
@end deffn
@node Options<4>,,Debugging<2>,Compilation contexts<2>
-@anchor{cp/topics/contexts options}@anchor{11a}
+@anchor{cp/topics/contexts options}@anchor{12c}
@subsubsection Options
@@ -11454,16 +11922,17 @@ for seeing what the C++ bindings are doing at the C level.
* String Options: String Options<2>.
* Boolean options: Boolean options<2>.
* Integer options: Integer options<2>.
+* Additional command-line options: Additional command-line options<2>.
@end menu
@node String Options<2>,Boolean options<2>,,Options<4>
-@anchor{cp/topics/contexts string-options}@anchor{11b}
+@anchor{cp/topics/contexts string-options}@anchor{12d}
@subsubsection String Options
@geindex gccjit;;context;;set_str_option (C++ function)
-@anchor{cp/topics/contexts gccjit context set_str_option__enum cCP}@anchor{11c}
+@anchor{cp/topics/contexts gccjit context set_str_option__enum cCP}@anchor{12e}
@deffn {C++ Function} void gccjit::context::set_str_option (enum gcc_jit_str_option, const char* value)
Set a string option of the context.
@@ -11474,12 +11943,12 @@ meaning.
@end deffn
@node Boolean options<2>,Integer options<2>,String Options<2>,Options<4>
-@anchor{cp/topics/contexts boolean-options}@anchor{11d}
+@anchor{cp/topics/contexts boolean-options}@anchor{12f}
@subsubsection Boolean options
@geindex gccjit;;context;;set_bool_option (C++ function)
-@anchor{cp/topics/contexts gccjit context set_bool_option__enum i}@anchor{eb}
+@anchor{cp/topics/contexts gccjit context set_bool_option__enum i}@anchor{fd}
@deffn {C++ Function} void gccjit::context::set_bool_option (enum gcc_jit_bool_option, int value)
Set a boolean option of the context.
@@ -11489,13 +11958,34 @@ This is a thin wrapper around the C API
meaning.
@end deffn
-@node Integer options<2>,,Boolean options<2>,Options<4>
-@anchor{cp/topics/contexts integer-options}@anchor{11e}
+@geindex gccjit;;context;;set_bool_allow_unreachable_blocks (C++ function)
+@anchor{cp/topics/contexts gccjit context set_bool_allow_unreachable_blocks__i}@anchor{130}
+@deffn {C++ Function} void gccjit::context::set_bool_allow_unreachable_blocks (int bool_value)
+
+By default, libgccjit will issue an error about unreachable blocks
+within a function.
+
+This entrypoint can be used to disable that error; it is a thin wrapper
+around the C API
+@pxref{6b,,gcc_jit_context_set_bool_allow_unreachable_blocks()}.
+
+This entrypoint was added in @pxref{6c,,LIBGCCJIT_ABI_2}; you can test for
+its presence using
+
+@example
+#ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
+@end example
+
+@noindent
+@end deffn
+
+@node Integer options<2>,Additional command-line options<2>,Boolean options<2>,Options<4>
+@anchor{cp/topics/contexts integer-options}@anchor{131}
@subsubsection Integer options
@geindex gccjit;;context;;set_int_option (C++ function)
-@anchor{cp/topics/contexts gccjit context set_int_option__enum i}@anchor{ec}
+@anchor{cp/topics/contexts gccjit context set_int_option__enum i}@anchor{fe}
@deffn {C++ Function} void gccjit::context::set_int_option (enum gcc_jit_int_option, int value)
Set an integer option of the context.
@@ -11505,6 +11995,31 @@ This is a thin wrapper around the C API
meaning.
@end deffn
+@node Additional command-line options<2>,,Integer options<2>,Options<4>
+@anchor{cp/topics/contexts additional-command-line-options}@anchor{132}
+@subsubsection Additional command-line options
+
+
+@geindex gccjit;;context;;add_command_line_option (C++ function)
+@anchor{cp/topics/contexts gccjit context add_command_line_option__cCP}@anchor{133}
+@deffn {C++ Function} void gccjit::context::add_command_line_option (const char* optname)
+
+Add an arbitrary gcc command-line option to the context for use
+when compiling.
+
+This is a thin wrapper around the C API
+@pxref{70,,gcc_jit_context_add_command_line_option()}.
+
+This entrypoint was added in @pxref{71,,LIBGCCJIT_ABI_1}; you can test for
+its presence using
+
+@example
+#ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
+@end example
+
+@noindent
+@end deffn
+
@c Copyright (C) 2014-2015 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -11523,18 +12038,18 @@ meaning.
@c <http://www.gnu.org/licenses/>.
@node Objects<2>,Types<2>,Compilation contexts<2>,Topic Reference<2>
-@anchor{cp/topics/objects objects}@anchor{11f}@anchor{cp/topics/objects doc}@anchor{120}
+@anchor{cp/topics/objects objects}@anchor{134}@anchor{cp/topics/objects doc}@anchor{135}
@subsection Objects
@geindex gccjit;;object (C++ class)
-@anchor{cp/topics/objects gccjit object}@anchor{121}
+@anchor{cp/topics/objects gccjit object}@anchor{136}
@deffn {C++ Class} gccjit::object
@end deffn
Almost every entity in the API (with the exception of
-@pxref{110,,gccjit;;context} and @pxref{16,,gcc_jit_result *}) is a
-"contextual" object, a @pxref{121,,gccjit;;object}.
+@pxref{122,,gccjit;;context} and @pxref{16,,gcc_jit_result *}) is a
+"contextual" object, a @pxref{136,,gccjit;;object}.
A JIT object:
@@ -11544,7 +12059,7 @@ A JIT object:
@itemize *
@item
-is associated with a @pxref{110,,gccjit;;context}.
+is associated with a @pxref{122,,gccjit;;context}.
@item
is automatically cleaned up for you when its context is released so
@@ -11566,21 +12081,22 @@ The C++ class hierarchy within the @code{gccjit} namespace looks like this:
+- rvalue
+- lvalue
+- param
+ +- case_
@end example
@noindent
-The @pxref{121,,gccjit;;object} base class has the following operations:
+The @pxref{136,,gccjit;;object} base class has the following operations:
@geindex gccjit;;object;;get_context (C++ function)
-@anchor{cp/topics/objects gccjit object get_contextC}@anchor{122}
+@anchor{cp/topics/objects gccjit object get_contextC}@anchor{137}
@deffn {C++ Function} gccjit::context gccjit::object::get_context () const
Which context is the obj within?
@end deffn
@geindex gccjit;;object;;get_debug_string (C++ function)
-@anchor{cp/topics/objects gccjit object get_debug_stringC}@anchor{e6}
+@anchor{cp/topics/objects gccjit object get_debug_stringC}@anchor{f8}
@deffn {C++ Function} std::string gccjit::object::get_debug_string () const
Generate a human-readable description for the given object.
@@ -11620,16 +12136,16 @@ obj: 4.0 * (float)i
@c <http://www.gnu.org/licenses/>.
@node Types<2>,Expressions<2>,Objects<2>,Topic Reference<2>
-@anchor{cp/topics/types doc}@anchor{123}@anchor{cp/topics/types types}@anchor{124}
+@anchor{cp/topics/types doc}@anchor{138}@anchor{cp/topics/types types}@anchor{139}
@subsection Types
@geindex gccjit;;type (C++ class)
-@anchor{cp/topics/types gccjit type}@anchor{125}
+@anchor{cp/topics/types gccjit type}@anchor{13a}
@deffn {C++ Class} gccjit::type
gccjit::type represents a type within the library. It is a subclass
-of @pxref{121,,gccjit;;object}.
+of @pxref{136,,gccjit;;object}.
@end deffn
Types can be created in several ways:
@@ -11639,7 +12155,7 @@ Types can be created in several ways:
@item
fundamental types can be accessed using
-@pxref{e4,,gccjit;;context;;get_type()}:
+@pxref{f6,,gccjit;;context;;get_type()}:
@example
gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
@@ -11659,7 +12175,7 @@ See @pxref{b,,gcc_jit_context_get_type()} for the available types.
@item
derived types can be accessed by using functions such as
-@pxref{126,,gccjit;;type;;get_pointer()} and @pxref{127,,gccjit;;type;;get_const()}:
+@pxref{13b,,gccjit;;type;;get_pointer()} and @pxref{13c,,gccjit;;type;;get_const()}:
@example
gccjit::type const_int_star = int_type.get_const ().get_pointer ();
@@ -11680,12 +12196,12 @@ by creating structures (see below).
@end menu
@node Standard types<2>,Pointers const and volatile<2>,,Types<2>
-@anchor{cp/topics/types standard-types}@anchor{128}
+@anchor{cp/topics/types standard-types}@anchor{13d}
@subsubsection Standard types
@geindex gccjit;;context;;get_type (C++ function)
-@anchor{cp/topics/types gccjit context get_type__enum}@anchor{e4}
+@anchor{cp/topics/types gccjit context get_type__enum}@anchor{f6}
@deffn {C++ Function} gccjit::type gccjit::context::get_type (enum gcc_jit_types)
Access a specific type. This is a thin wrapper around
@@ -11693,14 +12209,14 @@ Access a specific type. This is a thin wrapper around
@end deffn
@geindex gccjit;;context;;get_int_type (C++ function)
-@anchor{cp/topics/types gccjit context get_int_type__s i}@anchor{129}
+@anchor{cp/topics/types gccjit context get_int_type__s i}@anchor{13e}
@deffn {C++ Function} gccjit::type gccjit::context::get_int_type (size_t num_bytes, int is_signed)
Access the integer type of the given size.
@end deffn
@geindex gccjit;;context;;get_int_type<T> (C++ function)
-@anchor{cp/topics/types gccjit context get_int_type T}@anchor{12a}
+@anchor{cp/topics/types gccjit context get_int_type T}@anchor{13f}
@deffn {C++ Function} gccjit::type gccjit::context::get_int_type<T> ()
Access the given integer type. For example, you could map the
@@ -11714,12 +12230,12 @@ gccjit::type t = ctxt.get_int_type <unsigned short> ();
@end deffn
@node Pointers const and volatile<2>,Structures and unions<2>,Standard types<2>,Types<2>
-@anchor{cp/topics/types pointers-const-and-volatile}@anchor{12b}
+@anchor{cp/topics/types pointers-const-and-volatile}@anchor{140}
@subsubsection Pointers, @cite{const}, and @cite{volatile}
@geindex gccjit;;type;;get_pointer (C++ function)
-@anchor{cp/topics/types gccjit type get_pointer}@anchor{126}
+@anchor{cp/topics/types gccjit type get_pointer}@anchor{13b}
@deffn {C++ Function} gccjit::type gccjit::type::get_pointer ()
Given type "T", get type "T*".
@@ -11728,21 +12244,21 @@ Given type "T", get type "T*".
@c FIXME: get_const doesn't seem to exist
@geindex gccjit;;type;;get_const (C++ function)
-@anchor{cp/topics/types gccjit type get_const}@anchor{127}
+@anchor{cp/topics/types gccjit type get_const}@anchor{13c}
@deffn {C++ Function} gccjit::type gccjit::type::get_const ()
Given type "T", get type "const T".
@end deffn
@geindex gccjit;;type;;get_volatile (C++ function)
-@anchor{cp/topics/types gccjit type get_volatile}@anchor{12c}
+@anchor{cp/topics/types gccjit type get_volatile}@anchor{141}
@deffn {C++ Function} gccjit::type gccjit::type::get_volatile ()
Given type "T", get type "volatile T".
@end deffn
@geindex gccjit;;context;;new_array_type (C++ function)
-@anchor{cp/topics/types gccjit context new_array_type__gccjit type i gccjit location}@anchor{12d}
+@anchor{cp/topics/types gccjit context new_array_type__gccjit type i gccjit location}@anchor{142}
@deffn {C++ Function} gccjit::type gccjit::context::new_array_type (gccjit::type element_type, int num_elements, gccjit::location loc)
Given type "T", get type "T[N]" (for a constant N).
@@ -11750,31 +12266,31 @@ Param "loc" is optional.
@end deffn
@node Structures and unions<2>,,Pointers const and volatile<2>,Types<2>
-@anchor{cp/topics/types structures-and-unions}@anchor{12e}
+@anchor{cp/topics/types structures-and-unions}@anchor{143}
@subsubsection Structures and unions
@geindex gccjit;;struct_ (C++ class)
-@anchor{cp/topics/types gccjit struct_}@anchor{12f}
+@anchor{cp/topics/types gccjit struct_}@anchor{144}
@deffn {C++ Class} gccjit::struct_
@end deffn
A compound type analagous to a C @cite{struct}.
-@pxref{12f,,gccjit;;struct_} is a subclass of @pxref{125,,gccjit;;type} (and thus
-of @pxref{121,,gccjit;;object} in turn).
+@pxref{144,,gccjit;;struct_} is a subclass of @pxref{13a,,gccjit;;type} (and thus
+of @pxref{136,,gccjit;;object} in turn).
@geindex gccjit;;field (C++ class)
-@anchor{cp/topics/types gccjit field}@anchor{130}
+@anchor{cp/topics/types gccjit field}@anchor{145}
@deffn {C++ Class} gccjit::field
@end deffn
-A field within a @pxref{12f,,gccjit;;struct_}.
+A field within a @pxref{144,,gccjit;;struct_}.
-@pxref{130,,gccjit;;field} is a subclass of @pxref{121,,gccjit;;object}.
+@pxref{145,,gccjit;;field} is a subclass of @pxref{136,,gccjit;;object}.
-You can model C @cite{struct} types by creating @pxref{12f,,gccjit;;struct_} and
-@pxref{130,,gccjit;;field} instances, in either order:
+You can model C @cite{struct} types by creating @pxref{144,,gccjit;;struct_} and
+@pxref{145,,gccjit;;field} instances, in either order:
@itemize *
@@ -11830,14 +12346,14 @@ node.set_fields (fields);
@c FIXME: the above API doesn't seem to exist yet
@geindex gccjit;;context;;new_field (C++ function)
-@anchor{cp/topics/types gccjit context new_field__gccjit type cCP gccjit location}@anchor{131}
+@anchor{cp/topics/types gccjit context new_field__gccjit type cCP gccjit location}@anchor{146}
@deffn {C++ Function} gccjit::field gccjit::context::new_field (gccjit::type type, const char* name, gccjit::location loc)
Construct a new field, with the given type and name.
@end deffn
@geindex gccjit;;context;;new_struct_type (C++ function)
-@anchor{cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location}@anchor{132}
+@anchor{cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location}@anchor{147}
@deffn {C++ Function} gccjit::struct_ gccjit::context::new_struct_type (const std::string& name, std::vector<field>& fields, gccjit::location loc)
@quotation
@@ -11847,13 +12363,13 @@ Construct a new struct type, with the given name and fields.
@end deffn
@geindex gccjit;;context;;new_opaque_struct (C++ function)
-@anchor{cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location}@anchor{133}
+@anchor{cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location}@anchor{148}
@deffn {C++ Function} gccjit::struct_ gccjit::context::new_opaque_struct (const std::string& name, gccjit::location loc)
Construct a new struct type, with the given name, but without
specifying the fields. The fields can be omitted (in which case the
size of the struct is not known), or later specified using
-@pxref{80,,gcc_jit_struct_set_fields()}.
+@pxref{85,,gcc_jit_struct_set_fields()}.
@end deffn
@c Copyright (C) 2014-2015 Free Software Foundation, Inc.
@@ -11874,7 +12390,7 @@ size of the struct is not known), or later specified using
@c <http://www.gnu.org/licenses/>.
@node Expressions<2>,Creating and using functions<2>,Types<2>,Topic Reference<2>
-@anchor{cp/topics/expressions expressions}@anchor{134}@anchor{cp/topics/expressions doc}@anchor{135}
+@anchor{cp/topics/expressions expressions}@anchor{149}@anchor{cp/topics/expressions doc}@anchor{14a}
@subsection Expressions
@@ -11900,17 +12416,17 @@ Lvalues
@node Rvalues<2>,Lvalues<2>,,Expressions<2>
-@anchor{cp/topics/expressions rvalues}@anchor{136}
+@anchor{cp/topics/expressions rvalues}@anchor{14b}
@subsubsection Rvalues
@geindex gccjit;;rvalue (C++ class)
-@anchor{cp/topics/expressions gccjit rvalue}@anchor{137}
+@anchor{cp/topics/expressions gccjit rvalue}@anchor{14c}
@deffn {C++ Class} gccjit::rvalue
@end deffn
-A @pxref{137,,gccjit;;rvalue} is an expression that can be computed. It is a
-subclass of @pxref{121,,gccjit;;object}, and is a thin wrapper around
+A @pxref{14c,,gccjit;;rvalue} is an expression that can be computed. It is a
+subclass of @pxref{136,,gccjit;;object}, and is a thin wrapper around
@pxref{13,,gcc_jit_rvalue *} from the C API.
It can be simple, e.g.:
@@ -11956,7 +12472,7 @@ Every rvalue has an associated type, and the API will check to ensure
that types match up correctly (otherwise the context will emit an error).
@geindex gccjit;;rvalue;;get_type (C++ function)
-@anchor{cp/topics/expressions gccjit rvalue get_type}@anchor{138}
+@anchor{cp/topics/expressions gccjit rvalue get_type}@anchor{14d}
@deffn {C++ Function} gccjit::type gccjit::rvalue::get_type ()
Get the type of this rvalue.
@@ -11973,12 +12489,12 @@ Get the type of this rvalue.
@end menu
@node Simple expressions<2>,Unary Operations<2>,,Rvalues<2>
-@anchor{cp/topics/expressions simple-expressions}@anchor{139}
+@anchor{cp/topics/expressions simple-expressions}@anchor{14e}
@subsubsection Simple expressions
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type iC}@anchor{f8}
+@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type iC}@anchor{10a}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (gccjit::type numeric_type, int value) const
Given a numeric type (integer or floating point), build an rvalue for
@@ -11986,7 +12502,7 @@ the given constant @code{int} value.
@end deffn
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type lC}@anchor{13a}
+@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type lC}@anchor{14f}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (gccjit::type numeric_type, long value) const
Given a numeric type (integer or floating point), build an rvalue for
@@ -11994,7 +12510,7 @@ the given constant @code{long} value.
@end deffn
@geindex gccjit;;context;;zero (C++ function)
-@anchor{cp/topics/expressions gccjit context zero__gccjit typeC}@anchor{f4}
+@anchor{cp/topics/expressions gccjit context zero__gccjit typeC}@anchor{106}
@deffn {C++ Function} gccjit::rvalue gccjit::context::zero (gccjit::type numeric_type) const
Given a numeric type (integer or floating point), get the rvalue for
@@ -12008,7 +12524,7 @@ ctxt.new_rvalue (numeric_type, 0)
@end deffn
@geindex gccjit;;context;;one (C++ function)
-@anchor{cp/topics/expressions gccjit context one__gccjit typeC}@anchor{13b}
+@anchor{cp/topics/expressions gccjit context one__gccjit typeC}@anchor{150}
@deffn {C++ Function} gccjit::rvalue gccjit::context::one (gccjit::type numeric_type) const
Given a numeric type (integer or floating point), get the rvalue for
@@ -12022,7 +12538,7 @@ ctxt.new_rvalue (numeric_type, 1)
@end deffn
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC}@anchor{13c}
+@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC}@anchor{151}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (gccjit::type numeric_type, double value) const
Given a numeric type (integer or floating point), build an rvalue for
@@ -12030,14 +12546,14 @@ the given constant @code{double} value.
@end deffn
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC}@anchor{13d}
+@anchor{cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC}@anchor{152}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (gccjit::type pointer_type, void* value) const
Given a pointer type, build an rvalue for the given address.
@end deffn
@geindex gccjit;;context;;new_rvalue (C++ function)
-@anchor{cp/topics/expressions gccjit context new_rvalue__ssCRC}@anchor{13e}
+@anchor{cp/topics/expressions gccjit context new_rvalue__ssCRC}@anchor{153}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_rvalue (const std::string& value) const
Generate an rvalue of type @code{GCC_JIT_TYPE_CONST_CHAR_PTR} for
@@ -12045,12 +12561,12 @@ the given string. This is akin to a string literal.
@end deffn
@node Unary Operations<2>,Binary Operations<2>,Simple expressions<2>,Rvalues<2>
-@anchor{cp/topics/expressions unary-operations}@anchor{13f}
+@anchor{cp/topics/expressions unary-operations}@anchor{154}
@subsubsection Unary Operations
@geindex gccjit;;context;;new_unary_op (C++ function)
-@anchor{cp/topics/expressions gccjit context new_unary_op__enum gccjit type gccjit rvalue gccjit location}@anchor{140}
+@anchor{cp/topics/expressions gccjit context new_unary_op__enum gccjit type gccjit rvalue gccjit location}@anchor{155}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_unary_op (enum gcc_jit_unary_op, gccjit::type result_type, gccjit::rvalue rvalue, gccjit::location loc)
Build a unary operation out of an input rvalue.
@@ -12058,7 +12574,7 @@ Build a unary operation out of an input rvalue.
Parameter @code{loc} is optional.
This is a thin wrapper around the C API's
-@pxref{8c,,gcc_jit_context_new_unary_op()} and the available unary
+@pxref{91,,gcc_jit_context_new_unary_op()} and the available unary
operations are documented there.
@end deffn
@@ -12066,7 +12582,7 @@ There are shorter ways to spell the various specific kinds of unary
operation:
@geindex gccjit;;context;;new_minus (C++ function)
-@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location}@anchor{141}
+@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location}@anchor{156}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
Negate an arithmetic value; for example:
@@ -12087,7 +12603,7 @@ builds the equivalent of this C expression:
@end deffn
@geindex new_bitwise_negate (C++ function)
-@anchor{cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location}@anchor{142}
+@anchor{cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location}@anchor{157}
@deffn {C++ Function} gccjit::rvalue new_bitwise_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
Bitwise negation of an integer value (one's complement); for example:
@@ -12108,7 +12624,7 @@ builds the equivalent of this C expression:
@end deffn
@geindex new_logical_negate (C++ function)
-@anchor{cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location}@anchor{143}
+@anchor{cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location}@anchor{158}
@deffn {C++ Function} gccjit::rvalue new_logical_negate (gccjit::type result_type, gccjit::rvalue a, gccjit::location loc)
Logical negation of an arithmetic or pointer value; for example:
@@ -12131,7 +12647,7 @@ builds the equivalent of this C expression:
The most concise way to spell them is with overloaded operators:
@geindex operator- (C++ function)
-@anchor{cp/topics/expressions sub-operator__gccjit rvalue}@anchor{144}
+@anchor{cp/topics/expressions sub-operator__gccjit rvalue}@anchor{159}
@deffn {C++ Function} gccjit::rvalue operator- (gccjit::rvalue a)
@example
@@ -12142,7 +12658,7 @@ gccjit::rvalue negpi = -pi;
@end deffn
@geindex operator~ (C++ function)
-@anchor{cp/topics/expressions inv-operator__gccjit rvalue}@anchor{145}
+@anchor{cp/topics/expressions inv-operator__gccjit rvalue}@anchor{15a}
@deffn {C++ Function} gccjit::rvalue operator~ (gccjit::rvalue a)
@example
@@ -12153,7 +12669,7 @@ gccjit::rvalue mask = ~a;
@end deffn
@geindex operator! (C++ function)
-@anchor{cp/topics/expressions not-operator__gccjit rvalue}@anchor{146}
+@anchor{cp/topics/expressions not-operator__gccjit rvalue}@anchor{15b}
@deffn {C++ Function} gccjit::rvalue operator! (gccjit::rvalue a)
@example
@@ -12164,12 +12680,12 @@ gccjit::rvalue guard = !cond;
@end deffn
@node Binary Operations<2>,Comparisons<2>,Unary Operations<2>,Rvalues<2>
-@anchor{cp/topics/expressions binary-operations}@anchor{147}
+@anchor{cp/topics/expressions binary-operations}@anchor{15c}
@subsubsection Binary Operations
@geindex gccjit;;context;;new_binary_op (C++ function)
-@anchor{cp/topics/expressions gccjit context new_binary_op__enum gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{e8}
+@anchor{cp/topics/expressions gccjit context new_binary_op__enum gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{fa}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_binary_op (enum gcc_jit_binary_op, gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
Build a binary operation out of two constituent rvalues.
@@ -12185,59 +12701,59 @@ There are shorter ways to spell the various specific kinds of binary
operation:
@geindex gccjit;;context;;new_plus (C++ function)
-@anchor{cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{148}
+@anchor{cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{15d}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_plus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_minus (C++ function)
-@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{149}
+@anchor{cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{15e}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_minus (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_mult (C++ function)
-@anchor{cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{14a}
+@anchor{cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{15f}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_mult (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_divide (C++ function)
-@anchor{cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{14b}
+@anchor{cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{160}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_divide (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_modulo (C++ function)
-@anchor{cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{14c}
+@anchor{cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{161}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_modulo (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_bitwise_and (C++ function)
-@anchor{cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{14d}
+@anchor{cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{162}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_bitwise_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_bitwise_xor (C++ function)
-@anchor{cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{14e}
+@anchor{cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{163}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_bitwise_xor (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_bitwise_or (C++ function)
-@anchor{cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{14f}
+@anchor{cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{164}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_bitwise_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_logical_and (C++ function)
-@anchor{cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{150}
+@anchor{cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{165}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_logical_and (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_logical_or (C++ function)
-@anchor{cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{151}
+@anchor{cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location}@anchor{166}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_logical_or (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
The most concise way to spell them is with overloaded operators:
@geindex operator+ (C++ function)
-@anchor{cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue}@anchor{152}
+@anchor{cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue}@anchor{167}
@deffn {C++ Function} gccjit::rvalue operator+ (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12248,7 +12764,7 @@ gccjit::rvalue sum = a + b;
@end deffn
@geindex operator- (C++ function)
-@anchor{cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue}@anchor{153}
+@anchor{cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue}@anchor{168}
@deffn {C++ Function} gccjit::rvalue operator- (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12259,7 +12775,7 @@ gccjit::rvalue diff = a - b;
@end deffn
@geindex operator* (C++ function)
-@anchor{cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue}@anchor{154}
+@anchor{cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue}@anchor{169}
@deffn {C++ Function} gccjit::rvalue operator* (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12270,7 +12786,7 @@ gccjit::rvalue prod = a * b;
@end deffn
@geindex operator/ (C++ function)
-@anchor{cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue}@anchor{155}
+@anchor{cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue}@anchor{16a}
@deffn {C++ Function} gccjit::rvalue operator/ (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12281,7 +12797,7 @@ gccjit::rvalue result = a / b;
@end deffn
@geindex operator% (C++ function)
-@anchor{cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue}@anchor{156}
+@anchor{cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue}@anchor{16b}
@deffn {C++ Function} gccjit::rvalue operator% (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12292,7 +12808,7 @@ gccjit::rvalue mod = a % b;
@end deffn
@geindex operator& (C++ function)
-@anchor{cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue}@anchor{157}
+@anchor{cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue}@anchor{16c}
@deffn {C++ Function} gccjit::rvalue operator& (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12303,7 +12819,7 @@ gccjit::rvalue x = a & b;
@end deffn
@geindex operator^ (C++ function)
-@anchor{cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue}@anchor{158}
+@anchor{cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue}@anchor{16d}
@deffn {C++ Function} gccjit::rvalue operator^ (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12314,7 +12830,7 @@ gccjit::rvalue x = a ^ b;
@end deffn
@geindex operator| (C++ function)
-@anchor{cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue}@anchor{159}
+@anchor{cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue}@anchor{16e}
@deffn {C++ Function} gccjit::rvalue operator| (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12325,7 +12841,7 @@ gccjit::rvalue x = a | b;
@end deffn
@geindex operator&& (C++ function)
-@anchor{cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue}@anchor{15a}
+@anchor{cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue}@anchor{16f}
@deffn {C++ Function} gccjit::rvalue operator&& (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12336,7 +12852,7 @@ gccjit::rvalue cond = a && b;
@end deffn
@geindex operator|| (C++ function)
-@anchor{cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue}@anchor{15b}
+@anchor{cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue}@anchor{170}
@deffn {C++ Function} gccjit::rvalue operator|| (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12359,12 +12875,12 @@ gccjit::rvalue discriminant = (b * b) - (four * a * c);
@end quotation
@node Comparisons<2>,Function calls<2>,Binary Operations<2>,Rvalues<2>
-@anchor{cp/topics/expressions comparisons}@anchor{15c}
+@anchor{cp/topics/expressions comparisons}@anchor{171}
@subsubsection Comparisons
@geindex gccjit;;context;;new_comparison (C++ function)
-@anchor{cp/topics/expressions gccjit context new_comparison__enum gccjit rvalue gccjit rvalue gccjit location}@anchor{f5}
+@anchor{cp/topics/expressions gccjit context new_comparison__enum gccjit rvalue gccjit rvalue gccjit location}@anchor{107}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_comparison (enum gcc_jit_comparison, gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
Build a boolean rvalue out of the comparison of two other rvalues.
@@ -12380,39 +12896,39 @@ There are shorter ways to spell the various specific kinds of binary
operation:
@geindex gccjit;;context;;new_eq (C++ function)
-@anchor{cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location}@anchor{15d}
+@anchor{cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location}@anchor{172}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_eq (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_ne (C++ function)
-@anchor{cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location}@anchor{15e}
+@anchor{cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location}@anchor{173}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_ne (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_lt (C++ function)
-@anchor{cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location}@anchor{15f}
+@anchor{cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location}@anchor{174}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_lt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_le (C++ function)
-@anchor{cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location}@anchor{160}
+@anchor{cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location}@anchor{175}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_le (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_gt (C++ function)
-@anchor{cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location}@anchor{161}
+@anchor{cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location}@anchor{176}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_gt (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
@geindex gccjit;;context;;new_ge (C++ function)
-@anchor{cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location}@anchor{162}
+@anchor{cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location}@anchor{177}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_ge (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)
@end deffn
The most concise way to spell them is with overloaded operators:
@geindex operator== (C++ function)
-@anchor{cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue}@anchor{163}
+@anchor{cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue}@anchor{178}
@deffn {C++ Function} gccjit::rvalue operator== (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12423,7 +12939,7 @@ gccjit::rvalue cond = (a == ctxt.zero (t_int));
@end deffn
@geindex operator!= (C++ function)
-@anchor{cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue}@anchor{164}
+@anchor{cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue}@anchor{179}
@deffn {C++ Function} gccjit::rvalue operator!= (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12434,7 +12950,7 @@ gccjit::rvalue cond = (i != j);
@end deffn
@geindex operator< (C++ function)
-@anchor{cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue}@anchor{165}
+@anchor{cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue}@anchor{17a}
@deffn {C++ Function} gccjit::rvalue operator< (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12445,7 +12961,7 @@ gccjit::rvalue cond = i < n;
@end deffn
@geindex operator<= (C++ function)
-@anchor{cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue}@anchor{166}
+@anchor{cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue}@anchor{17b}
@deffn {C++ Function} gccjit::rvalue operator<= (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12456,7 +12972,7 @@ gccjit::rvalue cond = i <= n;
@end deffn
@geindex operator> (C++ function)
-@anchor{cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue}@anchor{167}
+@anchor{cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue}@anchor{17c}
@deffn {C++ Function} gccjit::rvalue operator> (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12467,7 +12983,7 @@ gccjit::rvalue cond = (ch > limit);
@end deffn
@geindex operator>= (C++ function)
-@anchor{cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue}@anchor{168}
+@anchor{cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue}@anchor{17d}
@deffn {C++ Function} gccjit::rvalue operator>= (gccjit::rvalue a, gccjit::rvalue b)
@example
@@ -12480,12 +12996,12 @@ gccjit::rvalue cond = (score >= ctxt.new_rvalue (t_int, 100));
@c TODO: beyond this point
@node Function calls<2>,Type-coercion<2>,Comparisons<2>,Rvalues<2>
-@anchor{cp/topics/expressions function-calls}@anchor{169}
+@anchor{cp/topics/expressions function-calls}@anchor{17e}
@subsubsection Function calls
@geindex gcc_jit_context_new_call (C++ function)
-@anchor{cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP}@anchor{16a}
+@anchor{cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP}@anchor{17f}
@deffn {C++ Function} gcc_jit_rvalue* gcc_jit_context_new_call (gcc_jit_context* ctxt, gcc_jit_location* loc, gcc_jit_function* func, int numargs, gcc_jit_rvalue** args)
Given a function and the given table of argument rvalues, construct a
@@ -12494,14 +13010,14 @@ call to the function, with the result as an rvalue.
@cartouche
@quotation Note
@code{gccjit::context::new_call()} merely builds a
-@pxref{137,,gccjit;;rvalue} i.e. an expression that can be evaluated,
+@pxref{14c,,gccjit;;rvalue} i.e. an expression that can be evaluated,
perhaps as part of a more complicated expression.
The call @emph{won't} happen unless you add a statement to a function
that evaluates the expression.
For example, if you want to call a function and discard the result
(or to call a function with @code{void} return type), use
-@pxref{16b,,gccjit;;block;;add_eval()}:
+@pxref{180,,gccjit;;block;;add_eval()}:
@example
/* Add "(void)printf (arg0, arg1);". */
@@ -12514,12 +13030,12 @@ block.add_eval (ctxt.new_call (printf_func, arg0, arg1));
@end deffn
@node Type-coercion<2>,,Function calls<2>,Rvalues<2>
-@anchor{cp/topics/expressions type-coercion}@anchor{16c}
+@anchor{cp/topics/expressions type-coercion}@anchor{181}
@subsubsection Type-coercion
@geindex gccjit;;context;;new_cast (C++ function)
-@anchor{cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location}@anchor{16d}
+@anchor{cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location}@anchor{182}
@deffn {C++ Function} gccjit::rvalue gccjit::context::new_cast (gccjit::rvalue rvalue, gccjit::type type, gccjit::location loc)
Given an rvalue of T, construct another rvalue of another type.
@@ -12544,24 +13060,24 @@ P* <-> Q*, for pointer types P and Q
@end deffn
@node Lvalues<2>,Working with pointers structs and unions<2>,Rvalues<2>,Expressions<2>
-@anchor{cp/topics/expressions lvalues}@anchor{16e}
+@anchor{cp/topics/expressions lvalues}@anchor{183}
@subsubsection Lvalues
@geindex gccjit;;lvalue (C++ class)
-@anchor{cp/topics/expressions gccjit lvalue}@anchor{16f}
+@anchor{cp/topics/expressions gccjit lvalue}@anchor{184}
@deffn {C++ Class} gccjit::lvalue
@end deffn
An lvalue is something that can of the @emph{left}-hand side of an assignment:
a storage area (such as a variable). It is a subclass of
-@pxref{137,,gccjit;;rvalue}, where the rvalue is computed by reading from the
+@pxref{14c,,gccjit;;rvalue}, where the rvalue is computed by reading from the
storage area.
It iss a thin wrapper around @pxref{24,,gcc_jit_lvalue *} from the C API.
@geindex gccjit;;lvalue;;get_address (C++ function)
-@anchor{cp/topics/expressions gccjit lvalue get_address__gccjit location}@anchor{170}
+@anchor{cp/topics/expressions gccjit lvalue get_address__gccjit location}@anchor{185}
@deffn {C++ Function} gccjit::rvalue gccjit::lvalue::get_address (gccjit::location loc)
Take the address of an lvalue; analogous to:
@@ -12583,27 +13099,27 @@ Parameter "loc" is optional.
@end menu
@node Global variables<2>,,,Lvalues<2>
-@anchor{cp/topics/expressions global-variables}@anchor{171}
+@anchor{cp/topics/expressions global-variables}@anchor{186}
@subsubsection Global variables
@geindex gccjit;;context;;new_global (C++ function)
-@anchor{cp/topics/expressions gccjit context new_global__enum gccjit type cCP gccjit location}@anchor{172}
+@anchor{cp/topics/expressions gccjit context new_global__enum gccjit type cCP gccjit location}@anchor{187}
@deffn {C++ Function} gccjit::lvalue gccjit::context::new_global (enum gcc_jit_global_kind, gccjit::type type, const char* name, gccjit::location loc)
Add a new global variable of the given type and name to the context.
-This is a thin wrapper around @pxref{ad,,gcc_jit_context_new_global()} from
+This is a thin wrapper around @pxref{b2,,gcc_jit_context_new_global()} from
the C API; the "kind" parameter has the same meaning as there.
@end deffn
@node Working with pointers structs and unions<2>,,Lvalues<2>,Expressions<2>
-@anchor{cp/topics/expressions working-with-pointers-structs-and-unions}@anchor{173}
+@anchor{cp/topics/expressions working-with-pointers-structs-and-unions}@anchor{188}
@subsubsection Working with pointers, structs and unions
@geindex gccjit;;rvalue;;dereference (C++ function)
-@anchor{cp/topics/expressions gccjit rvalue dereference__gccjit location}@anchor{174}
+@anchor{cp/topics/expressions gccjit rvalue dereference__gccjit location}@anchor{189}
@deffn {C++ Function} gccjit::lvalue gccjit::rvalue::dereference (gccjit::location loc)
Given an rvalue of pointer type @code{T *}, dereferencing the pointer,
@@ -12623,8 +13139,9 @@ Parameter "loc" is optional.
If you don't need to specify the location, this can also be expressed using
an overloaded operator:
-
-@deffn {C++ Function} gccjit::lvalue gccjit::rvalue::operator* ();
+@geindex gccjit;;rvalue;;operator* (C++ function)
+@anchor{cp/topics/expressions gccjit rvalue mul-operator}@anchor{18a}
+@deffn {C++ Function} gccjit::lvalue gccjit::rvalue::operator* ()
@example
gccjit::lvalue content = *ptr;
@@ -12636,7 +13153,7 @@ gccjit::lvalue content = *ptr;
Field access is provided separately for both lvalues and rvalues:
@geindex gccjit;;lvalue;;access_field (C++ function)
-@anchor{cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location}@anchor{175}
+@anchor{cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location}@anchor{18b}
@deffn {C++ Function} gccjit::lvalue gccjit::lvalue::access_field (gccjit::field field, gccjit::location loc)
Given an lvalue of struct or union type, access the given field,
@@ -12652,7 +13169,7 @@ in C.
@end deffn
@geindex gccjit;;rvalue;;access_field (C++ function)
-@anchor{cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location}@anchor{176}
+@anchor{cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location}@anchor{18c}
@deffn {C++ Function} gccjit::rvalue gccjit::rvalue::access_field (gccjit::field field, gccjit::location loc)
Given an rvalue of struct or union type, access the given field
@@ -12668,7 +13185,7 @@ in C.
@end deffn
@geindex gccjit;;rvalue;;dereference_field (C++ function)
-@anchor{cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location}@anchor{177}
+@anchor{cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location}@anchor{18d}
@deffn {C++ Function} gccjit::lvalue gccjit::rvalue::dereference_field (gccjit::field field, gccjit::location loc)
Given an rvalue of pointer type @code{T *} where T is of struct or union
@@ -12684,7 +13201,7 @@ in C, itself equivalent to @code{(*EXPR).FIELD}.
@end deffn
@geindex gccjit;;context;;new_array_access (C++ function)
-@anchor{cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location}@anchor{178}
+@anchor{cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location}@anchor{18e}
@deffn {C++ Function} gccjit::lvalue gccjit::context::new_array_access (gccjit::rvalue ptr, gccjit::rvalue index, gccjit::location loc)
Given an rvalue of pointer type @code{T *}, get at the element @cite{T} at
@@ -12703,7 +13220,7 @@ in C (or, indeed, to @code{PTR + INDEX}).
Parameter "loc" is optional.
@end deffn
-For array accesses where you don't need to specify a @pxref{118,,gccjit;;location},
+For array accesses where you don't need to specify a @pxref{12a,,gccjit;;location},
two overloaded operators are available:
@quotation
@@ -12743,7 +13260,7 @@ gccjit::lvalue element = array[0];
@c <http://www.gnu.org/licenses/>.
@node Creating and using functions<2>,Source Locations<2>,Expressions<2>,Topic Reference<2>
-@anchor{cp/topics/functions doc}@anchor{179}@anchor{cp/topics/functions creating-and-using-functions}@anchor{17a}
+@anchor{cp/topics/functions doc}@anchor{18f}@anchor{cp/topics/functions creating-and-using-functions}@anchor{190}
@subsection Creating and using functions
@@ -12756,44 +13273,45 @@ gccjit::lvalue element = array[0];
@end menu
@node Params<2>,Functions<2>,,Creating and using functions<2>
-@anchor{cp/topics/functions params}@anchor{17b}
+@anchor{cp/topics/functions params}@anchor{191}
@subsubsection Params
@geindex gccjit;;param (C++ class)
-@anchor{cp/topics/functions gccjit param}@anchor{17c}
+@anchor{cp/topics/functions gccjit param}@anchor{192}
@deffn {C++ Class} gccjit::param
A @cite{gccjit::param} represents a parameter to a function.
@end deffn
@geindex gccjit;;context;;new_param (C++ function)
-@anchor{cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location}@anchor{e7}
+@anchor{cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location}@anchor{f9}
@deffn {C++ Function} gccjit::param gccjit::context::new_param (gccjit::type type, const char* name, gccjit::location loc)
In preparation for creating a function, create a new parameter of the
given type and name.
@end deffn
-@pxref{17c,,gccjit;;param} is a subclass of @pxref{16f,,gccjit;;lvalue} (and thus
-of @pxref{137,,gccjit;;rvalue} and @pxref{121,,gccjit;;object}). It is a thin
+@pxref{192,,gccjit;;param} is a subclass of @pxref{184,,gccjit;;lvalue} (and thus
+of @pxref{14c,,gccjit;;rvalue} and @pxref{136,,gccjit;;object}). It is a thin
wrapper around the C API's @pxref{25,,gcc_jit_param *}.
@node Functions<2>,Blocks<2>,Params<2>,Creating and using functions<2>
-@anchor{cp/topics/functions functions}@anchor{17d}
+@anchor{cp/topics/functions functions}@anchor{193}
@subsubsection Functions
@geindex gccjit;;function (C++ class)
-@anchor{cp/topics/functions gccjit function}@anchor{17e}
+@anchor{cp/topics/functions gccjit function}@anchor{194}
@deffn {C++ Class} gccjit::function
A @cite{gccjit::function} represents a function - either one that we're
creating ourselves, or one that we're referencing.
@end deffn
-
-@deffn {C++ Function} gccjit::function gccjit::context::new_function (enum gcc_jit_function_kind, gccjit::type return_type, const char *name, std::vector<param> &params, int is_variadic, gccjit::location loc) \
+@geindex gccjit;;context;;new_function (C++ function)
+@anchor{cp/topics/functions gccjit context new_function__enum gccjit type cCP std vector param R i gccjit location}@anchor{195}
+@deffn {C++ Function} gccjit::function gccjit::context::new_function (enum gcc_jit_function_kind, gccjit::type return_type, const char* name, std::vector<param>& params, int is_variadic, gccjit::location loc)
Create a gcc_jit_function with the given name and parameters.
@@ -12803,29 +13321,29 @@ This is a wrapper around the C API's @pxref{11,,gcc_jit_context_new_function()}.
@end deffn
@geindex gccjit;;context;;get_builtin_function (C++ function)
-@anchor{cp/topics/functions gccjit context get_builtin_function__cCP}@anchor{17f}
+@anchor{cp/topics/functions gccjit context get_builtin_function__cCP}@anchor{196}
@deffn {C++ Function} gccjit::function gccjit::context::get_builtin_function (const char* name)
This is a wrapper around the C API's
-@pxref{c4,,gcc_jit_context_get_builtin_function()}.
+@pxref{c9,,gcc_jit_context_get_builtin_function()}.
@end deffn
@geindex gccjit;;function;;get_param (C++ function)
-@anchor{cp/topics/functions gccjit function get_param__iC}@anchor{180}
+@anchor{cp/topics/functions gccjit function get_param__iC}@anchor{197}
@deffn {C++ Function} gccjit::param gccjit::function::get_param (int index) const
Get the param of the given index (0-based).
@end deffn
@geindex gccjit;;function;;dump_to_dot (C++ function)
-@anchor{cp/topics/functions gccjit function dump_to_dot__cCP}@anchor{fa}
+@anchor{cp/topics/functions gccjit function dump_to_dot__cCP}@anchor{10c}
@deffn {C++ Function} void gccjit::function::dump_to_dot (const char* path)
Emit the function in graphviz format to the given path.
@end deffn
@geindex gccjit;;function;;new_local (C++ function)
-@anchor{cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location}@anchor{f1}
+@anchor{cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location}@anchor{103}
@deffn {C++ Function} gccjit::lvalue gccjit::function::new_local (gccjit::type type, const char* name, gccjit::location loc)
Create a new local variable within the function, of the given type and
@@ -12833,32 +13351,33 @@ name.
@end deffn
@node Blocks<2>,Statements<2>,Functions<2>,Creating and using functions<2>
-@anchor{cp/topics/functions blocks}@anchor{181}
+@anchor{cp/topics/functions blocks}@anchor{198}
@subsubsection Blocks
@geindex gccjit;;block (C++ class)
-@anchor{cp/topics/functions gccjit block}@anchor{182}
+@anchor{cp/topics/functions gccjit block}@anchor{199}
@deffn {C++ Class} gccjit::block
A @cite{gccjit::block} represents a basic block within a function i.e. a
sequence of statements with a single entry point and a single exit
point.
-@pxref{182,,gccjit;;block} is a subclass of @pxref{121,,gccjit;;object}.
+@pxref{199,,gccjit;;block} is a subclass of @pxref{136,,gccjit;;object}.
The first basic block that you create within a function will
be the entrypoint.
Each basic block that you create within a function must be
-terminated, either with a conditional, a jump, or a return.
+terminated, either with a conditional, a jump, a return, or
+a switch.
It's legal to have multiple basic blocks that return within
one function.
@end deffn
@geindex gccjit;;function;;new_block (C++ function)
-@anchor{cp/topics/functions gccjit function new_block__cCP}@anchor{183}
+@anchor{cp/topics/functions gccjit function new_block__cCP}@anchor{19a}
@deffn {C++ Function} gccjit::block gccjit::function::new_block (const char* name)
Create a basic block of the given name. The name may be NULL, but
@@ -12868,12 +13387,12 @@ messages.
@end deffn
@node Statements<2>,,Blocks<2>,Creating and using functions<2>
-@anchor{cp/topics/functions statements}@anchor{184}
+@anchor{cp/topics/functions statements}@anchor{19b}
@subsubsection Statements
@geindex gccjit;;block;;add_eval (C++ function)
-@anchor{cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location}@anchor{16b}
+@anchor{cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location}@anchor{180}
@deffn {C++ Function} void gccjit::block::add_eval (gccjit::rvalue rvalue, gccjit::location loc)
Add evaluation of an rvalue, discarding the result
@@ -12889,7 +13408,7 @@ This is equivalent to this C code:
@end deffn
@geindex gccjit;;block;;add_assignment (C++ function)
-@anchor{cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location}@anchor{f3}
+@anchor{cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location}@anchor{105}
@deffn {C++ Function} void gccjit::block::add_assignment (gccjit::lvalue lvalue, gccjit::rvalue rvalue, gccjit::location loc)
Add evaluation of an rvalue, assigning the result to the given
@@ -12905,7 +13424,7 @@ lvalue = rvalue;
@end deffn
@geindex gccjit;;block;;add_assignment_op (C++ function)
-@anchor{cp/topics/functions gccjit block add_assignment_op__gccjit lvalue enum gccjit rvalue gccjit location}@anchor{f7}
+@anchor{cp/topics/functions gccjit block add_assignment_op__gccjit lvalue enum gccjit rvalue gccjit location}@anchor{109}
@deffn {C++ Function} void gccjit::block::add_assignment_op (gccjit::lvalue lvalue, enum gcc_jit_binary_op, gccjit::rvalue rvalue, gccjit::location loc)
Add evaluation of an rvalue, using the result to modify an
@@ -12935,7 +13454,7 @@ loop_body.add_assignment_op (
@end deffn
@geindex gccjit;;block;;add_comment (C++ function)
-@anchor{cp/topics/functions gccjit block add_comment__cCP gccjit location}@anchor{102}
+@anchor{cp/topics/functions gccjit block add_comment__cCP gccjit location}@anchor{114}
@deffn {C++ Function} void gccjit::block::add_comment (const char* text, gccjit::location loc)
Add a no-op textual comment to the internal representation of the
@@ -12949,7 +13468,7 @@ Parameter "loc" is optional.
@end deffn
@geindex gccjit;;block;;end_with_conditional (C++ function)
-@anchor{cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location}@anchor{f6}
+@anchor{cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location}@anchor{108}
@deffn {C++ Function} void gccjit::block::end_with_conditional (gccjit::rvalue boolval, gccjit::block on_true, gccjit::block on_false, gccjit::location loc)
Terminate a block by adding evaluation of an rvalue, branching on the
@@ -12970,7 +13489,7 @@ block, boolval, on_true, and on_false must be non-NULL.
@end deffn
@geindex gccjit;;block;;end_with_jump (C++ function)
-@anchor{cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location}@anchor{185}
+@anchor{cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location}@anchor{19c}
@deffn {C++ Function} void gccjit::block::end_with_jump (gccjit::block target, gccjit::location loc)
Terminate a block by adding a jump to the given target block.
@@ -12985,7 +13504,7 @@ goto target;
@end deffn
@geindex gccjit;;block;;end_with_return (C++ function)
-@anchor{cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location}@anchor{186}
+@anchor{cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location}@anchor{19d}
@deffn {C++ Function} void gccjit::block::end_with_return (gccjit::rvalue rvalue, gccjit::location loc)
Terminate a block.
@@ -13018,6 +13537,174 @@ return;
@noindent
@end deffn
+@geindex gccjit;;block;;end_with_switch (C++ function)
+@anchor{cp/topics/functions gccjit block end_with_switch__gccjit rvalue gccjit block std vector gccjit case_ gccjit location}@anchor{19e}
+@deffn {C++ Function} void gccjit::block::end_with_switch (gccjit::rvalue expr, gccjit::block default_block, std::vector<gccjit::case_> cases, gccjit::location loc)
+
+Terminate a block by adding evalation of an rvalue, then performing
+a multiway branch.
+
+This is roughly equivalent to this C code:
+
+@example
+switch (expr)
+ @{
+ default:
+ goto default_block;
+
+ case C0.min_value ... C0.max_value:
+ goto C0.dest_block;
+
+ case C1.min_value ... C1.max_value:
+ goto C1.dest_block;
+
+ ...etc...
+
+ case C[N - 1].min_value ... C[N - 1].max_value:
+ goto C[N - 1].dest_block;
+@}
+@end example
+
+@noindent
+
+@code{expr} must be of the same integer type as all of the @code{min_value}
+and @code{max_value} within the cases.
+
+The ranges of the cases must not overlap (or have duplicate
+values).
+
+The API entrypoints relating to switch statements and cases:
+
+@quotation
+
+
+@itemize *
+
+@item
+@pxref{19e,,gccjit;;block;;end_with_switch()}
+
+@item
+@pxref{19f,,gccjit;;context;;new_case()}
+@end itemize
+@end quotation
+
+were added in @pxref{d7,,LIBGCCJIT_ABI_3}; you can test for their presence
+using
+
+@example
+#ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
+@end example
+
+@noindent
+
+@geindex gccjit;;block;;end_with_switch;;gccjit;;case_ (C++ class)
+@anchor{cp/topics/functions gccjit block end_with_switch gccjit case_}@anchor{1a0}
+@deffn {C++ Class} gccjit::case_
+@end deffn
+
+A @cite{gccjit::case_} represents a case within a switch statement, and
+is created within a particular @pxref{122,,gccjit;;context} using
+@pxref{19f,,gccjit;;context;;new_case()}. It is a subclass of
+@pxref{136,,gccjit;;object}.
+
+Each case expresses a multivalued range of integer values. You
+can express single-valued cases by passing in the same value for
+both @cite{min_value} and @cite{max_value}.
+
+@geindex gccjit;;block;;end_with_switch;;gccjit;;context;;new_case (C++ function)
+@anchor{cp/topics/functions gccjit block end_with_switch gccjit context new_case__gccjit rvalue gccjit rvalue gccjit block}@anchor{19f}
+@deffn {C++ Function} gccjit::case_* gccjit::context::new_case (gccjit::rvalue min_value, gccjit::rvalue max_value, gccjit::block dest_block)
+
+Create a new gccjit::case for use in a switch statement.
+@cite{min_value} and @cite{max_value} must be constants of an integer type,
+which must match that of the expression of the switch statement.
+
+@cite{dest_block} must be within the same function as the switch
+statement.
+@end deffn
+
+Here's an example of creating a switch statement:
+
+@quotation
+
+@example
+
+void
+create_code (gcc_jit_context *c_ctxt, void *user_data)
+@{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ @{
+ switch (x)
+ @{
+ case 0 ... 5:
+ return 3;
+
+ case 25 ... 27:
+ return 4;
+
+ case -42 ... -17:
+ return 83;
+
+ case 40:
+ return 8;
+
+ default:
+ return 10;
+ @}
+ @}
+ */
+ gccjit::context ctxt (c_ctxt);
+ gccjit::type t_int = ctxt.get_type (GCC_JIT_TYPE_INT);
+ gccjit::type return_type = t_int;
+ gccjit::param x = ctxt.new_param (t_int, "x");
+ std::vector <gccjit::param> params;
+ params.push_back (x);
+ gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ params, 0);
+
+ gccjit::block b_initial = func.new_block ("initial");
+
+ gccjit::block b_default = func.new_block ("default");
+ gccjit::block b_case_0_5 = func.new_block ("case_0_5");
+ gccjit::block b_case_25_27 = func.new_block ("case_25_27");
+ gccjit::block b_case_m42_m17 = func.new_block ("case_m42_m17");
+ gccjit::block b_case_40 = func.new_block ("case_40");
+
+ std::vector <gccjit::case_> cases;
+ cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 0),
+ ctxt.new_rvalue (t_int, 5),
+ b_case_0_5));
+ cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 25),
+ ctxt.new_rvalue (t_int, 27),
+ b_case_25_27));
+ cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, -42),
+ ctxt.new_rvalue (t_int, -17),
+ b_case_m42_m17));
+ cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 40),
+ ctxt.new_rvalue (t_int, 40),
+ b_case_40));
+ b_initial.end_with_switch (x,
+ b_default,
+ cases);
+
+ b_case_0_5.end_with_return (ctxt.new_rvalue (t_int, 3));
+ b_case_25_27.end_with_return (ctxt.new_rvalue (t_int, 4));
+ b_case_m42_m17.end_with_return (ctxt.new_rvalue (t_int, 83));
+ b_case_40.end_with_return (ctxt.new_rvalue (t_int, 8));
+ b_default.end_with_return (ctxt.new_rvalue (t_int, 10));
+@}
+
+
+@end example
+
+@noindent
+@end quotation
+@end deffn
+
@c Copyright (C) 2014-2015 Free Software Foundation, Inc.
@c Originally contributed by David Malcolm <dmalcolm@redhat.com>
@c
@@ -13036,12 +13723,12 @@ return;
@c <http://www.gnu.org/licenses/>.
@node Source Locations<2>,Compiling a context<2>,Creating and using functions<2>,Topic Reference<2>
-@anchor{cp/topics/locations source-locations}@anchor{187}@anchor{cp/topics/locations doc}@anchor{188}
+@anchor{cp/topics/locations source-locations}@anchor{1a1}@anchor{cp/topics/locations doc}@anchor{1a2}
@subsection Source Locations
@geindex gccjit;;location (C++ class)
-@anchor{cp/topics/locations gccjit location}@anchor{118}
+@anchor{cp/topics/locations gccjit location}@anchor{12a}
@deffn {C++ Class} gccjit::location
A @cite{gccjit::location} encapsulates a source code location, so that
@@ -13052,10 +13739,10 @@ single-step through your language.
@cite{gccjit::location} instances are optional: you can always omit them
from any C++ API entrypoint accepting one.
-You can construct them using @pxref{106,,gccjit;;context;;new_location()}.
+You can construct them using @pxref{118,,gccjit;;context;;new_location()}.
You need to enable @pxref{42,,GCC_JIT_BOOL_OPTION_DEBUGINFO} on the
-@pxref{110,,gccjit;;context} for these locations to actually be usable by
+@pxref{122,,gccjit;;context} for these locations to actually be usable by
the debugger:
@example
@@ -13066,7 +13753,7 @@ ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
@end deffn
@geindex gccjit;;context;;new_location (C++ function)
-@anchor{cp/topics/locations gccjit context new_location__cCP i i}@anchor{106}
+@anchor{cp/topics/locations gccjit context new_location__cCP i i}@anchor{118}
@deffn {C++ Function} gccjit::location gccjit::context::new_location (const char* filename, int line, int column)
Create a @cite{gccjit::location} instance representing the given source
@@ -13079,13 +13766,13 @@ location.
@end menu
@node Faking it<2>,,,Source Locations<2>
-@anchor{cp/topics/locations faking-it}@anchor{189}
+@anchor{cp/topics/locations faking-it}@anchor{1a3}
@subsubsection Faking it
If you don't have source code for your internal representation, but need
to debug, you can generate a C-like representation of the functions in
-your context using @pxref{117,,gccjit;;context;;dump_to_file()}:
+your context using @pxref{129,,gccjit;;context;;dump_to_file()}:
@example
ctxt.dump_to_file ("/tmp/something.c",
@@ -13117,13 +13804,13 @@ file, giving you @emph{something} you can step through in the debugger.
@c <http://www.gnu.org/licenses/>.
@node Compiling a context<2>,,Source Locations<2>,Topic Reference<2>
-@anchor{cp/topics/compilation compiling-a-context}@anchor{18a}@anchor{cp/topics/compilation doc}@anchor{18b}
+@anchor{cp/topics/compilation compiling-a-context}@anchor{1a4}@anchor{cp/topics/compilation doc}@anchor{1a5}
@subsection Compiling a context
-Once populated, a @pxref{110,,gccjit;;context} can be compiled to
-machine code, either in-memory via @pxref{e9,,gccjit;;context;;compile()} or
-to disk via @pxref{18c,,gccjit;;context;;compile_to_file()}.
+Once populated, a @pxref{122,,gccjit;;context} can be compiled to
+machine code, either in-memory via @pxref{fb,,gccjit;;context;;compile()} or
+to disk via @pxref{1a6,,gccjit;;context;;compile_to_file()}.
You can compile a context multiple times (using either form of
compilation), although any errors that occur on the context will
@@ -13136,12 +13823,12 @@ prevent any future compilation of that context.
@end menu
@node In-memory compilation<2>,Ahead-of-time compilation<2>,,Compiling a context<2>
-@anchor{cp/topics/compilation in-memory-compilation}@anchor{18d}
+@anchor{cp/topics/compilation in-memory-compilation}@anchor{1a7}
@subsubsection In-memory compilation
@geindex gccjit;;context;;compile (C++ function)
-@anchor{cp/topics/compilation gccjit context compile}@anchor{e9}
+@anchor{cp/topics/compilation gccjit context compile}@anchor{fb}
@deffn {C++ Function} gcc_jit_result* gccjit::context::compile ()
This calls into GCC and builds the code, returning a
@@ -13152,19 +13839,19 @@ This is a thin wrapper around the
@end deffn
@node Ahead-of-time compilation<2>,,In-memory compilation<2>,Compiling a context<2>
-@anchor{cp/topics/compilation ahead-of-time-compilation}@anchor{18e}
+@anchor{cp/topics/compilation ahead-of-time-compilation}@anchor{1a8}
@subsubsection Ahead-of-time compilation
Although libgccjit is primarily aimed at just-in-time compilation, it
can also be used for implementing more traditional ahead-of-time
-compilers, via the @pxref{18c,,gccjit;;context;;compile_to_file()} method.
+compilers, via the @pxref{1a6,,gccjit;;context;;compile_to_file()} method.
@geindex gccjit;;context;;compile_to_file (C++ function)
-@anchor{cp/topics/compilation gccjit context compile_to_file__enum cCP}@anchor{18c}
+@anchor{cp/topics/compilation gccjit context compile_to_file__enum cCP}@anchor{1a6}
@deffn {C++ Function} void gccjit::context::compile_to_file (enum gcc_jit_output_kind, const char* output_path)
-Compile the @pxref{110,,gccjit;;context} to a file of the given
+Compile the @pxref{122,,gccjit;;context} to a file of the given
kind.
This is a thin wrapper around the
@@ -13189,7 +13876,7 @@ This is a thin wrapper around the
@c <http://www.gnu.org/licenses/>.
@node Internals,Indices and tables,C++ bindings for libgccjit,Top
-@anchor{internals/index internals}@anchor{18f}@anchor{internals/index doc}@anchor{190}
+@anchor{internals/index internals}@anchor{1a9}@anchor{internals/index doc}@anchor{1aa}
@chapter Internals
@@ -13204,7 +13891,7 @@ This is a thin wrapper around the
@end menu
@node Working on the JIT library,Running the test suite,,Internals
-@anchor{internals/index working-on-the-jit-library}@anchor{191}
+@anchor{internals/index working-on-the-jit-library}@anchor{1ab}
@section Working on the JIT library
@@ -13241,7 +13928,7 @@ gcc/libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
Here's what those configuration options mean:
@geindex command line option; --enable-host-shared
-@anchor{internals/index cmdoption--enable-host-shared}@anchor{192}
+@anchor{internals/index cmdoption--enable-host-shared}@anchor{1ac}
@deffn {Option} --enable-host-shared
Configuring with this option means that the compiler is built as
@@ -13250,7 +13937,7 @@ but it necessary for a shared library.
@end deffn
@geindex command line option; --enable-languages=jit@comma{}c++
-@anchor{internals/index cmdoption--enable-languages}@anchor{193}
+@anchor{internals/index cmdoption--enable-languages}@anchor{1ad}
@deffn {Option} --enable-languages=jit,c++
This specifies which frontends to build. The JIT library looks like
@@ -13269,7 +13956,7 @@ c++: error trying to exec 'cc1plus': execvp: No such file or directory
@end deffn
@geindex command line option; --disable-bootstrap
-@anchor{internals/index cmdoption--disable-bootstrap}@anchor{194}
+@anchor{internals/index cmdoption--disable-bootstrap}@anchor{1ae}
@deffn {Option} --disable-bootstrap
For hacking on the "jit" subdirectory, performing a full
@@ -13279,7 +13966,7 @@ the compiler can still bootstrap itself.
@end deffn
@geindex command line option; --enable-checking=release
-@anchor{internals/index cmdoption--enable-checking}@anchor{195}
+@anchor{internals/index cmdoption--enable-checking}@anchor{1af}
@deffn {Option} --enable-checking=release
The compile can perform extensive self-checking as it runs, useful when
@@ -13290,7 +13977,7 @@ disable this self-checking.
@end deffn
@node Running the test suite,Environment variables,Working on the JIT library,Internals
-@anchor{internals/index running-the-test-suite}@anchor{196}
+@anchor{internals/index running-the-test-suite}@anchor{1b0}
@section Running the test suite
@@ -13353,7 +14040,7 @@ and once a test has been compiled, you can debug it directly:
@end menu
@node Running under valgrind,,,Running the test suite
-@anchor{internals/index running-under-valgrind}@anchor{197}
+@anchor{internals/index running-under-valgrind}@anchor{1b1}
@subsection Running under valgrind
@@ -13401,7 +14088,7 @@ When running under valgrind, it's best to have configured gcc with
various known false positives.
@node Environment variables,Packaging notes,Running the test suite,Internals
-@anchor{internals/index environment-variables}@anchor{198}
+@anchor{internals/index environment-variables}@anchor{1b2}
@section Environment variables
@@ -13409,7 +14096,7 @@ When running client code against a locally-built libgccjit, three
environment variables need to be set up:
@geindex environment variable; LD_LIBRARY_PATH
-@anchor{internals/index envvar-LD_LIBRARY_PATH}@anchor{199}
+@anchor{internals/index envvar-LD_LIBRARY_PATH}@anchor{1b3}
@deffn {Environment Variable} LD_LIBRARY_PATH
@quotation
@@ -13431,7 +14118,7 @@ libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux),
@end deffn
@geindex environment variable; PATH
-@anchor{internals/index envvar-PATH}@anchor{19a}
+@anchor{internals/index envvar-PATH}@anchor{1b4}
@deffn {Environment Variable} PATH
The library uses a driver executable for converting from .s assembler
@@ -13450,7 +14137,7 @@ of development.
@end deffn
@geindex environment variable; LIBRARY_PATH
-@anchor{internals/index envvar-LIBRARY_PATH}@anchor{19b}
+@anchor{internals/index envvar-LIBRARY_PATH}@anchor{1b5}
@deffn {Environment Variable} LIBRARY_PATH
The driver executable invokes the linker, and the latter needs to locate
@@ -13486,11 +14173,11 @@ hello world
@noindent
@node Packaging notes,Overview of code structure,Environment variables,Internals
-@anchor{internals/index packaging-notes}@anchor{19c}
+@anchor{internals/index packaging-notes}@anchor{1b6}
@section Packaging notes
-The configure-time option @pxref{192,,--enable-host-shared} is needed when
+The configure-time option @pxref{1ac,,--enable-host-shared} is needed when
building the jit in order to get position-independent code. This will
slow down the regular compiler by a few percent. Hence when packaging gcc
with libgccjit, please configure and build twice:
@@ -13501,10 +14188,10 @@ with libgccjit, please configure and build twice:
@itemize *
@item
-once without @pxref{192,,--enable-host-shared} for most languages, and
+once without @pxref{1ac,,--enable-host-shared} for most languages, and
@item
-once with @pxref{192,,--enable-host-shared} for the jit
+once with @pxref{1ac,,--enable-host-shared} for the jit
@end itemize
@end quotation
@@ -13548,7 +14235,7 @@ popd
@noindent
@node Overview of code structure,Design notes,Packaging notes,Internals
-@anchor{internals/index overview-of-code-structure}@anchor{19d}
+@anchor{internals/index overview-of-code-structure}@anchor{1b7}
@section Overview of code structure
@@ -13588,6 +14275,7 @@ The gcc::jit::recording classes (within @code{jit-recording.c} and
class global;
class param;
class statement;
+ class case_;
@end example
@@ -13618,6 +14306,7 @@ within langhook:parse_file:
class source_file;
class source_line;
class location;
+ class case_;
@end example
@@ -14012,7 +14701,7 @@ JIT: gcc::jit::logger::~logger()
@noindent
@node Design notes,,Overview of code structure,Internals
-@anchor{internals/index design-notes}@anchor{19e}
+@anchor{internals/index design-notes}@anchor{1b8}
@section Design notes
@@ -14025,7 +14714,7 @@ close as possible to the error; failing that, a good place is within
@code{recording::context::validate ()} in jit-recording.c.
@node Indices and tables,Index,Internals,Top
-@anchor{index indices-and-tables}@anchor{19f}
+@anchor{index indices-and-tables}@anchor{1b9}
@unnumbered Indices and tables
diff --git a/gcc/jit/docs/cp/topics/contexts.rst b/gcc/jit/docs/cp/topics/contexts.rst
index 12a4e507c84..162e4aec8f3 100644
--- a/gcc/jit/docs/cp/topics/contexts.rst
+++ b/gcc/jit/docs/cp/topics/contexts.rst
@@ -184,6 +184,23 @@ Boolean options
:c:func:`gcc_jit_context_set_bool_option`; the options have the same
meaning.
+.. function:: void \
+ gccjit::context::set_bool_allow_unreachable_blocks (int bool_value)
+
+ By default, libgccjit will issue an error about unreachable blocks
+ within a function.
+
+ This entrypoint can be used to disable that error; it is a thin wrapper
+ around the C API
+ :c:func:`gcc_jit_context_set_bool_allow_unreachable_blocks`.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_2`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
+
Integer options
***************
@@ -196,3 +213,22 @@ Integer options
This is a thin wrapper around the C API
:c:func:`gcc_jit_context_set_int_option`; the options have the same
meaning.
+
+Additional command-line options
+*******************************
+
+.. function:: void \
+ gccjit::context::add_command_line_option (const char *optname)
+
+ Add an arbitrary gcc command-line option to the context for use
+ when compiling.
+
+ This is a thin wrapper around the C API
+ :c:func:`gcc_jit_context_add_command_line_option`.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_1`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
diff --git a/gcc/jit/docs/cp/topics/expressions.rst b/gcc/jit/docs/cp/topics/expressions.rst
index 4ea2622dde5..ac8d4f15392 100644
--- a/gcc/jit/docs/cp/topics/expressions.rst
+++ b/gcc/jit/docs/cp/topics/expressions.rst
@@ -535,7 +535,7 @@ If you don't need to specify the location, this can also be expressed using
an overloaded operator:
.. function:: gccjit::lvalue \
- gccjit::rvalue::operator* ();
+ gccjit::rvalue::operator* ()
.. code-block:: c++
diff --git a/gcc/jit/docs/cp/topics/functions.rst b/gcc/jit/docs/cp/topics/functions.rst
index a31b2787f7d..57b6298bc83 100644
--- a/gcc/jit/docs/cp/topics/functions.rst
+++ b/gcc/jit/docs/cp/topics/functions.rst
@@ -52,7 +52,7 @@ Functions
const char *name, \
std::vector<param> &params, \
int is_variadic, \
- gccjit::location loc) \
+ gccjit::location loc)
Create a gcc_jit_function with the given name and parameters.
@@ -98,7 +98,8 @@ Blocks
be the entrypoint.
Each basic block that you create within a function must be
- terminated, either with a conditional, a jump, or a return.
+ terminated, either with a conditional, a jump, a return, or
+ a switch.
It's legal to have multiple basic blocks that return within
one function.
@@ -241,3 +242,82 @@ Statements
.. code-block:: c
return;
+
+.. function:: void\
+ gccjit::block::end_with_switch (gccjit::rvalue expr,\
+ gccjit::block default_block,\
+ std::vector <gccjit::case_> cases,\
+ gccjit::location loc)
+
+ Terminate a block by adding evalation of an rvalue, then performing
+ a multiway branch.
+
+ This is roughly equivalent to this C code:
+
+ .. code-block:: c
+
+ switch (expr)
+ {
+ default:
+ goto default_block;
+
+ case C0.min_value ... C0.max_value:
+ goto C0.dest_block;
+
+ case C1.min_value ... C1.max_value:
+ goto C1.dest_block;
+
+ ...etc...
+
+ case C[N - 1].min_value ... C[N - 1].max_value:
+ goto C[N - 1].dest_block;
+ }
+
+ ``expr`` must be of the same integer type as all of the ``min_value``
+ and ``max_value`` within the cases.
+
+ The ranges of the cases must not overlap (or have duplicate
+ values).
+
+ The API entrypoints relating to switch statements and cases:
+
+ * :func:`gccjit::block::end_with_switch`
+
+ * :func:`gccjit::context::new_case`
+
+ were added in :ref:`LIBGCCJIT_ABI_3`; you can test for their presence
+ using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
+
+ .. class:: gccjit::case_
+
+ A `gccjit::case_` represents a case within a switch statement, and
+ is created within a particular :class:`gccjit::context` using
+ :func:`gccjit::context::new_case`. It is a subclass of
+ :class:`gccjit::object`.
+
+ Each case expresses a multivalued range of integer values. You
+ can express single-valued cases by passing in the same value for
+ both `min_value` and `max_value`.
+
+ .. function:: gccjit::case_ *\
+ gccjit::context::new_case (gccjit::rvalue min_value,\
+ gccjit::rvalue max_value,\
+ gccjit::block dest_block)
+
+ Create a new gccjit::case for use in a switch statement.
+ `min_value` and `max_value` must be constants of an integer type,
+ which must match that of the expression of the switch statement.
+
+ `dest_block` must be within the same function as the switch
+ statement.
+
+ Here's an example of creating a switch statement:
+
+ .. literalinclude:: ../../../../testsuite/jit.dg/test-switch.cc
+ :start-after: /* Quote from here in docs/cp/topics/functions.rst. */
+ :end-before: /* Quote up to here in docs/cp/topics/functions.rst. */
+ :language: c++
diff --git a/gcc/jit/docs/cp/topics/objects.rst b/gcc/jit/docs/cp/topics/objects.rst
index 714b645a690..8d99bd40df8 100644
--- a/gcc/jit/docs/cp/topics/objects.rst
+++ b/gcc/jit/docs/cp/topics/objects.rst
@@ -46,6 +46,7 @@ The C++ class hierarchy within the ``gccjit`` namespace looks like this::
+- rvalue
+- lvalue
+- param
+ +- case_
The :class:`gccjit::object` base class has the following operations:
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
new file mode 100644
index 00000000000..37e28665e70
--- /dev/null
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -0,0 +1,109 @@
+.. Copyright (C) 2015 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <dmalcolm@redhat.com>
+
+ This is free software: you can 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 this program. If not, see
+ <http://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+ABI and API compatibility
+=========================
+
+The libgccjit developers strive for ABI and API backward-compatibility:
+programs built against libgccjit.so stand a good chance of running
+without recompilation against newer versions of libgccjit.so, and
+ought to recompile without modification against newer versions of
+libgccjit.h.
+
+.. note:: The libgccjit++.h C++ API is more experimental, and less
+ locked-down at this time.
+
+API compatibility is achieved by extending the API rather than changing
+it. For ABI compatiblity, we avoid bumping the SONAME, and instead use
+symbol versioning to tag each symbol, so that a binary linked against
+libgccjit.so is tagged according to the symbols that it uses.
+
+For example, :func:`gcc_jit_context_add_command_line_option` was added in
+``LIBGCCJIT_ABI_1``. If a client program uses it, this can be detected
+from metadata by using ``objdump``:
+
+.. code-block:: bash
+
+ $ objdump -p testsuite/jit/test-extra-options.c.exe | tail -n 8
+
+ Version References:
+ required from libgccjit.so.0:
+ 0x00824161 0x00 04 LIBGCCJIT_ABI_1
+ 0x00824160 0x00 03 LIBGCCJIT_ABI_0
+ required from libc.so.6:
+
+You can see the symbol tags provided by libgccjit.so using ``objdump``:
+
+.. code-block:: bash
+
+ $ objdump -p libgccjit.so | less
+ [...snip...]
+ Version definitions:
+ 1 0x01 0x0ff81f20 libgccjit.so.0
+ 2 0x00 0x00824160 LIBGCCJIT_ABI_0
+ 3 0x00 0x00824161 LIBGCCJIT_ABI_1
+ LIBGCCJIT_ABI_0
+ [...snip...]
+
+ABI symbol tags
+***************
+
+The initial release of libgccjit (in gcc 5.1) did not use symbol versioning.
+
+Newer releases use the following tags.
+
+.. _LIBGCCJIT_ABI_0:
+
+``LIBGCCJIT_ABI_0``
+-------------------
+
+All entrypoints in the initial release of libgccjit are tagged with
+``LIBGCCJIT_ABI_0``, to signify the transition to symbol versioning.
+
+Binaries built against older copies of ``libgccjit.so`` should
+continue to work, with this being handled transparently by the linker
+(see `this post
+<https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02126.html>`_)
+
+.. _LIBGCCJIT_ABI_1:
+
+``LIBGCCJIT_ABI_1``
+-------------------
+``LIBGCCJIT_ABI_1`` covers the addition of
+:func:`gcc_jit_context_add_command_line_option`
+
+.. _LIBGCCJIT_ABI_2:
+
+``LIBGCCJIT_ABI_2``
+-------------------
+``LIBGCCJIT_ABI_2`` covers the addition of
+:func:`gcc_jit_context_set_bool_allow_unreachable_blocks`
+
+.. _LIBGCCJIT_ABI_3:
+
+``LIBGCCJIT_ABI_3``
+-------------------
+``LIBGCCJIT_ABI_3`` covers the addition of switch statements via API
+entrypoints:
+
+ * :func:`gcc_jit_block_end_with_switch`
+
+ * :func:`gcc_jit_case_as_object`
+
+ * :func:`gcc_jit_context_new_case`
diff --git a/gcc/jit/docs/topics/contexts.rst b/gcc/jit/docs/topics/contexts.rst
index b7f281a5e69..1dd4685a4c8 100644
--- a/gcc/jit/docs/topics/contexts.rst
+++ b/gcc/jit/docs/topics/contexts.rst
@@ -293,6 +293,15 @@ future activies on a context to the given `FILE *`.
Options
-------
+Options present in the initial release of libgccjit were handled using
+enums, whereas those added subsequently have their own per-option API
+entrypoints.
+
+Adding entrypoints for each new option means that client code that use
+the new options can be identified directly from binary metadata, which
+would not be possible if we instead extended the various
+``enum gcc_jit_*_option``.
+
String Options
**************
@@ -304,7 +313,7 @@ String Options
.. type:: enum gcc_jit_str_option
- There is currently just one string option:
+ There is just one string option specified this way:
.. macro:: GCC_JIT_STR_OPTION_PROGNAME
@@ -441,6 +450,22 @@ Boolean options
If true, the :type:`gcc_jit_context` will not clean up intermediate files
written to the filesystem, and will display their location on stderr.
+.. function:: void \
+ gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt, \
+ int bool_value)
+
+ By default, libgccjit will issue an error about unreachable blocks
+ within a function.
+
+ This entrypoint can be used to disable that error.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_2`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
+
Integer options
***************
@@ -452,7 +477,7 @@ Integer options
.. type:: enum gcc_jit_int_option
- There is currently just one integer option:
+ There is just one integer option specified this way:
.. macro:: GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
@@ -462,3 +487,39 @@ Integer options
-O0 through -O3.
The default value is 0 (unoptimized).
+
+Additional command-line options
+*******************************
+
+.. function:: void gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,\
+ const char *optname)
+
+ Add an arbitrary gcc command-line option to the context, for use
+ by :func:`gcc_jit_context_compile` and
+ :func:`gcc_jit_context_compile_to_file`.
+
+ The parameter ``optname`` must be non-NULL. The underlying buffer is
+ copied, so that it does not need to outlive the call.
+
+ Extra options added by `gcc_jit_context_add_command_line_option` are
+ applied *after* the regular options above, potentially overriding them.
+ Options from parent contexts are inherited by child contexts; options
+ from the parent are applied *before* those from the child.
+
+ For example:
+
+ .. code-block:: c
+
+ gcc_jit_context_add_command_line_option (ctxt, "-ffast-math");
+ gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm");
+
+ Note that only some options are likely to be meaningful; there is no
+ "frontend" within libgccjit, so typically only those affecting
+ optimization and code-generation are likely to be useful.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_1`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index 774a5565743..94db471615c 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -153,7 +153,8 @@ Blocks
be the entrypoint.
Each basic block that you create within a function must be
- terminated, either with a conditional, a jump, or a return.
+ terminated, either with a conditional, a jump, a return, or a
+ switch.
It's legal to have multiple basic blocks that return within
one function.
@@ -313,3 +314,96 @@ Statements
.. code-block:: c
return;
+
+.. function:: void\
+ gcc_jit_block_end_with_switch (gcc_jit_block *block,\
+ gcc_jit_location *loc,\
+ gcc_jit_rvalue *expr,\
+ gcc_jit_block *default_block,\
+ int num_cases,\
+ gcc_jit_case **cases)
+
+ Terminate a block by adding evalation of an rvalue, then performing
+ a multiway branch.
+
+ This is roughly equivalent to this C code:
+
+ .. code-block:: c
+
+ switch (expr)
+ {
+ default:
+ goto default_block;
+
+ case C0.min_value ... C0.max_value:
+ goto C0.dest_block;
+
+ case C1.min_value ... C1.max_value:
+ goto C1.dest_block;
+
+ ...etc...
+
+ case C[N - 1].min_value ... C[N - 1].max_value:
+ goto C[N - 1].dest_block;
+ }
+
+ ``block``, ``expr``, ``default_block`` and ``cases`` must all be
+ non-NULL.
+
+ ``expr`` must be of the same integer type as all of the ``min_value``
+ and ``max_value`` within the cases.
+
+ ``num_cases`` must be >= 0.
+
+ The ranges of the cases must not overlap (or have duplicate
+ values).
+
+ The API entrypoints relating to switch statements and cases:
+
+ * :c:func:`gcc_jit_block_end_with_switch`
+
+ * :c:func:`gcc_jit_case_as_object`
+
+ * :c:func:`gcc_jit_context_new_case`
+
+ were added in :ref:`LIBGCCJIT_ABI_3`; you can test for their presence
+ using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
+
+ .. type:: gcc_jit_case
+
+ A `gcc_jit_case` represents a case within a switch statement, and
+ is created within a particular :c:type:`gcc_jit_context` using
+ :c:func:`gcc_jit_context_new_case`.
+
+ Each case expresses a multivalued range of integer values. You
+ can express single-valued cases by passing in the same value for
+ both `min_value` and `max_value`.
+
+ .. function:: gcc_jit_case *\
+ gcc_jit_context_new_case (gcc_jit_context *ctxt,\
+ gcc_jit_rvalue *min_value,\
+ gcc_jit_rvalue *max_value,\
+ gcc_jit_block *dest_block)
+
+ Create a new gcc_jit_case instance for use in a switch statement.
+ `min_value` and `max_value` must be constants of an integer type,
+ which must match that of the expression of the switch statement.
+
+ `dest_block` must be within the same function as the switch
+ statement.
+
+ .. function:: gcc_jit_object *\
+ gcc_jit_case_as_object (gcc_jit_case *case_)
+
+ Upcast from a case to an object.
+
+ Here's an example of creating a switch statement:
+
+ .. literalinclude:: ../../../testsuite/jit.dg/test-switch.c
+ :start-after: /* Quote from here in docs/topics/functions.rst. */
+ :end-before: /* Quote up to here in docs/topics/functions.rst. */
+ :language: c
diff --git a/gcc/jit/docs/topics/index.rst b/gcc/jit/docs/topics/index.rst
index 4ebb623de0b..76b3d0b9b53 100644
--- a/gcc/jit/docs/topics/index.rst
+++ b/gcc/jit/docs/topics/index.rst
@@ -28,3 +28,4 @@ Topic Reference
functions.rst
locations.rst
compilation.rst
+ compatibility.rst
diff --git a/gcc/jit/docs/topics/objects.rst b/gcc/jit/docs/topics/objects.rst
index 3ae63097ed2..85c783ca2bb 100644
--- a/gcc/jit/docs/topics/objects.rst
+++ b/gcc/jit/docs/topics/objects.rst
@@ -47,6 +47,7 @@ looks like this::
+- gcc_jit_rvalue
+- gcc_jit_lvalue
+- gcc_jit_param
+ +- gcc_jit_case
There are casting methods for upcasting from subclasses to parent classes.
For example, :c:func:`gcc_jit_type_as_object`:
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index e5e1a1e688a..3397215bc91 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -129,6 +129,7 @@ namespace recording {
class global;
class param;
class statement;
+ class case_;
/* End of recording types. */
}
@@ -150,6 +151,7 @@ namespace playback {
class source_file;
class source_line;
class location;
+ class case_;
/* End of playback types. */
}
@@ -185,6 +187,16 @@ private:
FILE *m_file;
};
+/* A hidden enum of boolean options that are only exposed via API
+ entrypoints, rather than via gcc_jit_context_set_bool_option. */
+
+enum inner_bool_option
+{
+ INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS,
+
+ NUM_INNER_BOOL_OPTIONS
+};
+
} // namespace gcc::jit
} // namespace gcc
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 90a6cd1eeb1..c9d7c8c607a 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -1576,6 +1576,80 @@ add_return (location *loc,
add_stmt (return_stmt);
}
+/* Helper function for playback::block::add_switch.
+ Construct a case label for the given range, followed by a goto stmt
+ to the given block, appending them to stmt list *ptr_t_switch_body. */
+
+static void
+add_case (tree *ptr_t_switch_body,
+ tree t_low_value,
+ tree t_high_value,
+ playback::block *dest_block)
+{
+ tree t_label = create_artificial_label (UNKNOWN_LOCATION);
+ DECL_CONTEXT (t_label) = dest_block->get_function ()->as_fndecl ();
+
+ tree t_case_label =
+ build_case_label (t_low_value, t_high_value, t_label);
+ append_to_statement_list (t_case_label, ptr_t_switch_body);
+
+ tree t_goto_stmt =
+ build1 (GOTO_EXPR, void_type_node, dest_block->as_label_decl ());
+ append_to_statement_list (t_goto_stmt, ptr_t_switch_body);
+}
+
+/* Add a switch statement to the function's statement list.
+
+ My initial attempt at implementing this constructed a TREE_VEC
+ of the cases and set it as SWITCH_LABELS (switch_expr). However,
+ gimplify.c:gimplify_switch_expr is set up to deal with SWITCH_BODY, and
+ doesn't have any logic for gimplifying SWITCH_LABELS.
+
+ Hence we create a switch body, and populate it with case labels, each
+ followed by a goto to the desired block. */
+
+void
+playback::block::
+add_switch (location *loc,
+ rvalue *expr,
+ block *default_block,
+ const auto_vec <case_> *cases)
+{
+ /* Compare with:
+ - c/c-typeck.c: c_start_case
+ - c-family/c-common.c:c_add_case_label
+ - java/expr.c:expand_java_switch and expand_java_add_case
+ We've already rejected overlaps and duplicates in
+ libgccjit.c:case_range_validator::validate. */
+
+ tree t_expr = expr->as_tree ();
+ tree t_type = TREE_TYPE (t_expr);
+
+ tree t_switch_body = alloc_stmt_list ();
+
+ int i;
+ case_ *c;
+ FOR_EACH_VEC_ELT (*cases, i, c)
+ {
+ tree t_low_value = c->m_min_value->as_tree ();
+ tree t_high_value = c->m_max_value->as_tree ();
+ add_case (&t_switch_body,
+ t_low_value,
+ t_high_value,
+ c->m_dest_block);
+ }
+ /* Default label. */
+ add_case (&t_switch_body,
+ NULL_TREE, NULL_TREE,
+ default_block);
+
+ tree switch_stmt = build3 (SWITCH_EXPR, t_type, t_expr,
+ t_switch_body, NULL_TREE);
+ if (loc)
+ set_tree_location (switch_stmt, loc);
+ add_stmt (switch_stmt);
+}
+
/* Constructor for gcc::jit::playback::block. */
playback::block::
@@ -2139,6 +2213,10 @@ make_fake_args (vec <char *> *argvec,
}
}
+ /* Add any user-provided extra options, starting with any from
+ parent contexts. */
+ m_recording_ctxt->append_command_line_options (argvec);
+
#undef ADD_ARG
#undef ADD_ARG_TAKE_OWNERSHIP
}
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index a6de5661b4d..13cc748135f 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -437,6 +437,19 @@ private:
vec<block *> m_blocks;
};
+struct case_
+{
+ case_ (rvalue *min_value, rvalue *max_value, block *dest_block)
+ : m_min_value (min_value),
+ m_max_value (max_value),
+ m_dest_block (dest_block)
+ {}
+
+ rvalue *m_min_value;
+ rvalue *m_max_value;
+ block *m_dest_block;
+};
+
class block : public wrapper
{
public:
@@ -447,6 +460,8 @@ public:
tree as_label_decl () const { return m_label_decl; }
+ function *get_function () const { return m_func; }
+
void
add_eval (location *loc,
rvalue *rvalue);
@@ -478,6 +493,12 @@ public:
add_return (location *loc,
rvalue *rvalue);
+ void
+ add_switch (location *loc,
+ rvalue *expr,
+ block *default_block,
+ const auto_vec <case_> *cases);
+
private:
void
set_tree_location (tree t, location *loc)
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index f379b58ec81..a653205040e 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -489,6 +489,9 @@ recording::context::context (context *parent_ctxt)
memcpy (m_bool_options,
parent_ctxt->m_bool_options,
sizeof (m_bool_options));
+ memcpy (m_inner_bool_options,
+ parent_ctxt->m_inner_bool_options,
+ sizeof (m_inner_bool_options));
set_logger (parent_ctxt->get_logger ());
}
else
@@ -496,6 +499,7 @@ recording::context::context (context *parent_ctxt)
memset (m_str_options, 0, sizeof (m_str_options));
memset (m_int_options, 0, sizeof (m_int_options));
memset (m_bool_options, 0, sizeof (m_bool_options));
+ memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
}
memset (m_basic_types, 0, sizeof (m_basic_types));
@@ -517,6 +521,10 @@ recording::context::~context ()
for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
free (m_str_options[i]);
+ char *optname;
+ FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
+ free (optname);
+
if (m_builtins_manager)
delete m_builtins_manager;
@@ -1076,6 +1084,22 @@ recording::context::new_array_access (recording::location *loc,
return result;
}
+/* Create a recording::case_ instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_case. */
+
+recording::case_ *
+recording::context::new_case (recording::rvalue *min_value,
+ recording::rvalue *max_value,
+ recording::block *block)
+{
+ recording::case_ *result = new case_ (this, min_value, max_value, block);
+ record (result);
+ return result;
+}
+
/* Set the given string option for this context, or add an error if
it's not recognized.
@@ -1137,6 +1161,43 @@ recording::context::set_bool_option (enum gcc_jit_bool_option opt,
log_bool_option (opt);
}
+void
+recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
+ int value)
+{
+ gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
+ m_inner_bool_options[inner_opt] = value ? true : false;
+ log_inner_bool_option (inner_opt);
+}
+
+
+/* Add the given optname to this context's list of extra options.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_add_command_line_option. */
+
+void
+recording::context::add_command_line_option (const char *optname)
+{
+ m_command_line_options.safe_push (xstrdup (optname));
+}
+
+/* Add any user-provided extra options, starting with any from
+ parent contexts.
+ Called by playback::context::make_fake_args. */
+
+void
+recording::context::append_command_line_options (vec <char *> *argvec)
+{
+ if (m_parent_ctxt)
+ m_parent_ctxt->append_command_line_options (argvec);
+
+ int i;
+ char *optname;
+ FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
+ argvec->safe_push (xstrdup (optname));
+}
+
/* Add the given dumpname/out_ptr pair to this context's list of requested
dumps.
@@ -1387,6 +1448,10 @@ static const char * const
"GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
};
+static const char * const
+ inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
+ "gcc_jit_context_set_bool_allow_unreachable_blocks"
+};
/* Write the current value of all options to the log file (if any). */
@@ -1406,6 +1471,8 @@ recording::context::log_all_options () const
for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
log_bool_option ((enum gcc_jit_bool_option)opt_idx);
+ for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
+ log_inner_bool_option ((enum inner_bool_option)opt_idx);
}
/* Write the current value of the given string option to the
@@ -1453,6 +1520,19 @@ recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
m_bool_options[opt] ? "true" : "false");
}
+/* Write the current value of the given "inner" bool option to the
+ log file (if any). */
+
+void
+recording::context::log_inner_bool_option (enum inner_bool_option opt) const
+{
+ gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
+ if (get_logger ())
+ log ("%s: %s",
+ inner_bool_option_reproducer_strings[opt],
+ m_inner_bool_options[opt] ? "true" : "false");
+}
+
/* Write C source code to PATH that attempts to replay the API
calls made to this context (and its parents), for use in
minimizing test cases for libgccjit.
@@ -1494,6 +1574,7 @@ recording::context::dump_reproducer_to_file (const char *path)
print_version (r.get_file (), " ", false);
r.write ("*/\n");
r.write ("#include <libgccjit.h>\n\n");
+ r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
r.write ("static void\nset_options (");
r.write_params (contexts);
r.write (");\n\n");
@@ -1564,12 +1645,17 @@ recording::context::dump_reproducer_to_file (const char *path)
r.write (" /* String options. */\n");
for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
- r.write (" gcc_jit_context_set_str_option (%s,\n"
- " %s,\n"
- " \"%s\");\n",
- r.get_identifier (contexts[ctxt_idx]),
- str_option_reproducer_strings[opt_idx],
- m_str_options[opt_idx] ? m_str_options[opt_idx] : "NULL");
+ {
+ r.write (" gcc_jit_context_set_str_option (%s,\n"
+ " %s,\n",
+ r.get_identifier (contexts[ctxt_idx]),
+ str_option_reproducer_strings[opt_idx]);
+ if (m_str_options[opt_idx])
+ r.write (" \"%s\");\n",
+ m_str_options[opt_idx]);
+ else
+ r.write (" NULL);\n");
+ }
r.write (" /* Int options. */\n");
for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
r.write (" gcc_jit_context_set_int_option (%s,\n"
@@ -1586,6 +1672,22 @@ recording::context::dump_reproducer_to_file (const char *path)
r.get_identifier (contexts[ctxt_idx]),
bool_option_reproducer_strings[opt_idx],
m_bool_options[opt_idx]);
+ for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
+ r.write (" %s (%s, %i);\n",
+ inner_bool_option_reproducer_strings[opt_idx],
+ r.get_identifier (contexts[ctxt_idx]),
+ m_inner_bool_options[opt_idx]);
+
+ if (!m_command_line_options.is_empty ())
+ {
+ int i;
+ char *optname;
+ r.write (" /* User-provided command-line options. */\n");
+ FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
+ r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
+ r.get_identifier (contexts[ctxt_idx]),
+ optname);
+ }
if (m_requested_dumps.length ())
{
@@ -3404,7 +3506,9 @@ recording::function::validate ()
}
/* Check that all blocks are reachable. */
- if (m_blocks.length () > 0 && 0 == num_invalid_blocks)
+ if (!m_ctxt->get_inner_bool_option
+ (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
+ && m_blocks.length () > 0 && 0 == num_invalid_blocks)
{
/* Iteratively walk the graph of blocks, marking their "m_is_reachable"
flag, starting at the initial block. */
@@ -3417,23 +3521,13 @@ recording::function::validate ()
/* Add successor blocks that aren't yet marked to the worklist. */
/* We checked that each block has a terminating statement above . */
- block *next1, *next2;
- int n = b->get_successor_blocks (&next1, &next2);
- switch (n)
- {
- default:
- gcc_unreachable ();
- case 2:
- if (!next2->m_is_reachable)
- worklist.safe_push (next2);
- /* fallthrough */
- case 1:
- if (!next1->m_is_reachable)
- worklist.safe_push (next1);
- break;
- case 0:
- break;
- }
+ vec <block *> successors = b->get_successor_blocks ();
+ int i;
+ block *succ;
+ FOR_EACH_VEC_ELT (successors, i, succ)
+ if (!succ->m_is_reachable)
+ worklist.safe_push (succ);
+ successors.release ();
}
/* Now complain about any blocks that haven't been marked. */
@@ -3681,6 +3775,30 @@ recording::block::end_with_return (recording::location *loc,
return result;
}
+/* Create a recording::switch_ instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the heart of gcc_jit_block_end_with_switch. */
+
+recording::statement *
+recording::block::end_with_switch (recording::location *loc,
+ recording::rvalue *expr,
+ recording::block *default_block,
+ int num_cases,
+ recording::case_ **cases)
+{
+ statement *result = new switch_ (this, loc,
+ expr,
+ default_block,
+ num_cases,
+ cases);
+ m_ctxt->record (result);
+ m_statements.safe_push (result);
+ m_has_been_terminated = true;
+ return result;
+}
+
/* Override the default implementation of
recording::memento::write_to_dump for blocks by writing
an unindented block name as a label, followed by the indented
@@ -3758,24 +3876,20 @@ recording::block::get_last_statement () const
return NULL;
}
-/* Assuming that this block has been terminated, get the number of
- successor blocks, which will be 0, 1 or 2, for return, unconditional
- jump, and conditional jump respectively.
- NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
- is written to NEXT1, and the second (if any) to NEXT2.
+/* Assuming that this block has been terminated, get the successor blocks
+ as a vector. Ownership of the vector transfers to the caller, which
+ must call its release () method.
Used when validating functions, and when dumping dot representations
of them. */
-int
-recording::block::get_successor_blocks (block **next1, block **next2) const
+vec <recording::block *>
+recording::block::get_successor_blocks () const
{
gcc_assert (m_has_been_terminated);
- gcc_assert (next1);
- gcc_assert (next2);
statement *last_statement = get_last_statement ();
gcc_assert (last_statement);
- return last_statement->get_successor_blocks (next1, next2);
+ return last_statement->get_successor_blocks ();
}
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -3853,12 +3967,14 @@ recording::block::dump_to_dot (pretty_printer *pp)
void
recording::block::dump_edges_to_dot (pretty_printer *pp)
{
- block *next[2];
- int num_succs = get_successor_blocks (&next[0], &next[1]);
- for (int i = 0; i < num_succs; i++)
+ vec <block *> successors = get_successor_blocks ();
+ int i;
+ block *succ;
+ FOR_EACH_VEC_ELT (successors, i, succ)
pp_printf (pp,
"\tblock_%d:s -> block_%d:n;\n",
- m_index, next[i]->m_index);
+ m_index, succ->m_index);
+ successors.release ();
}
/* The implementation of class gcc::jit::recording::global. */
@@ -4003,6 +4119,16 @@ memento_of_new_rvalue_from_const <int>::make_debug_string ()
m_value);
}
+/* The get_wide_int specialization for <int>. */
+
+template <>
+bool
+memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
+{
+ *out = wi::shwi (m_value, sizeof (m_value) * 8);
+ return true;
+}
+
/* The write_reproducer specialization for <int>. */
template <>
@@ -4035,6 +4161,16 @@ memento_of_new_rvalue_from_const <long>::make_debug_string ()
m_value);
}
+/* The get_wide_int specialization for <long>. */
+
+template <>
+bool
+memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
+{
+ *out = wi::shwi (m_value, sizeof (m_value) * 8);
+ return true;
+}
+
/* The write_reproducer specialization for <long>. */
template <>
@@ -4088,6 +4224,15 @@ memento_of_new_rvalue_from_const <double>::make_debug_string ()
m_value);
}
+/* The get_wide_int specialization for <double>. */
+
+template <>
+bool
+memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
+{
+ return false;
+}
+
/* The write_reproducer specialization for <double>. */
template <>
@@ -4127,6 +4272,15 @@ memento_of_new_rvalue_from_const <void *>::make_debug_string ()
m_type->get_debug_string ());
}
+/* The get_wide_int specialization for <void *>. */
+
+template <>
+bool
+memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
+{
+ return false;
+}
+
/* Implementation of recording::memento::write_reproducer for <void *>
values. */
@@ -5125,14 +5279,15 @@ recording::local::write_reproducer (reproducer &r)
since this vfunc must only ever be called on terminator
statements. */
-int
-recording::statement::get_successor_blocks (block **/*out_next1*/,
- block **/*out_next2*/) const
+vec <recording::block *>
+recording::statement::get_successor_blocks () const
{
/* The base class implementation is for non-terminating statements,
and thus should never be called. */
gcc_unreachable ();
- return 0;
+ vec <block *> result;
+ result.create (0);
+ return result;
}
/* Extend the default implementation of
@@ -5341,13 +5496,14 @@ recording::conditional::replay_into (replayer *r)
A conditional jump has 2 successor blocks. */
-int
-recording::conditional::get_successor_blocks (block **out_next1,
- block **out_next2) const
+vec <recording::block *>
+recording::conditional::get_successor_blocks () const
{
- *out_next1 = m_on_true;
- *out_next2 = m_on_false;
- return 2;
+ vec <block *> result;
+ result.create (2);
+ result.quick_push (m_on_true);
+ result.quick_push (m_on_false);
+ return result;
}
/* Implementation of recording::memento::make_debug_string for
@@ -5405,12 +5561,13 @@ recording::jump::replay_into (replayer *r)
An unconditional jump has 1 successor block. */
-int
-recording::jump::get_successor_blocks (block **out_next1,
- block **/*out_next2*/) const
+vec <recording::block *>
+recording::jump::get_successor_blocks () const
{
- *out_next1 = m_target;
- return 1;
+ vec <block *> result;
+ result.create (1);
+ result.quick_push (m_target);
+ return result;
}
/* Implementation of recording::memento::make_debug_string for
@@ -5456,11 +5613,12 @@ recording::return_::replay_into (replayer *r)
A return statement has no successor block. */
-int
-recording::return_::get_successor_blocks (block **/*out_next1*/,
- block **/*out_next2*/) const
+vec <recording::block *>
+recording::return_::get_successor_blocks () const
{
- return 0;
+ vec <block *> result;
+ result.create (0);
+ return result;
}
/* Implementation of recording::memento::make_debug_string for
@@ -5498,6 +5656,158 @@ recording::return_::write_reproducer (reproducer &r)
r.get_identifier (get_loc ()));
}
+/* The implementation of class gcc::jit::recording::case_. */
+
+void
+recording::case_::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "case");
+ const char *fmt =
+ " gcc_jit_case *%s = \n"
+ " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
+ " %s, /* gcc_jit_rvalue *min_value */\n"
+ " %s, /* gcc_jit_rvalue *max_value */\n"
+ " %s); /* gcc_jit_block *dest_block */\n";
+ r.write (fmt,
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier_as_rvalue (m_min_value),
+ r.get_identifier_as_rvalue (m_max_value),
+ r.get_identifier (m_dest_block));
+}
+
+recording::string *
+recording::case_::make_debug_string ()
+{
+ return string::from_printf (get_context (),
+ "case %s ... %s: goto %s;",
+ m_min_value->get_debug_string (),
+ m_max_value->get_debug_string (),
+ m_dest_block->get_debug_string ());
+}
+
+/* The implementation of class gcc::jit::recording::switch_. */
+
+/* gcc::jit::recording::switch_'s constructor. */
+
+recording::switch_::switch_ (block *b,
+ location *loc,
+ rvalue *expr,
+ block *default_block,
+ int num_cases,
+ case_ **cases)
+: statement (b, loc),
+ m_expr (expr),
+ m_default_block (default_block)
+{
+ m_cases.reserve_exact (num_cases);
+ for (int i = 0; i< num_cases; i++)
+ m_cases.quick_push (cases[i]);
+}
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::switch_. */
+
+void
+recording::switch_::replay_into (replayer *r)
+{
+ auto_vec <playback::case_> pcases;
+ int i;
+ recording::case_ *rcase;
+ pcases.reserve_exact (m_cases.length ());
+ FOR_EACH_VEC_ELT (m_cases, i, rcase)
+ {
+ playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
+ rcase->get_max_value ()->playback_rvalue (),
+ rcase->get_dest_block ()->playback_block ());
+ pcases.safe_push (pcase);
+ }
+ playback_block (get_block ())
+ ->add_switch (playback_location (r),
+ m_expr->playback_rvalue (),
+ m_default_block->playback_block (),
+ &pcases);
+}
+
+/* Override the poisoned default implementation of
+ gcc::jit::recording::statement::get_successor_blocks
+
+ A switch statement has (NUM_CASES + 1) successor blocks. */
+
+vec <recording::block *>
+recording::switch_::get_successor_blocks () const
+{
+ vec <block *> result;
+ result.create (m_cases.length () + 1);
+ result.quick_push (m_default_block);
+ int i;
+ case_ *c;
+ FOR_EACH_VEC_ELT (m_cases, i, c)
+ result.quick_push (c->get_dest_block ());
+ return result;
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ a switch statement. */
+
+recording::string *
+recording::switch_::make_debug_string ()
+{
+ auto_vec <char> cases_str;
+ int i;
+ case_ *c;
+ FOR_EACH_VEC_ELT (m_cases, i, c)
+ {
+ size_t len = strlen (c->get_debug_string ());
+ unsigned idx = cases_str.length ();
+ cases_str.safe_grow (idx + 1 + len);
+ cases_str[idx] = ' ';
+ memcpy (&(cases_str[idx + 1]),
+ c->get_debug_string (),
+ len);
+ }
+ cases_str.safe_push ('\0');
+
+ return string::from_printf (m_ctxt,
+ "switch (%s) {default: goto %s;%s}",
+ m_expr->get_debug_string (),
+ m_default_block->get_debug_string (),
+ &cases_str[0]);
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ switch statements. */
+
+void
+recording::switch_::write_reproducer (reproducer &r)
+{
+ r.make_identifier (this, "switch");
+ int i;
+ case_ *c;
+ const char *cases_id =
+ r.make_tmp_identifier ("cases_for", this);
+ r.write (" gcc_jit_case *%s[%i] = {\n",
+ cases_id,
+ m_cases.length ());
+ FOR_EACH_VEC_ELT (m_cases, i, c)
+ r.write (" %s,\n", r.get_identifier (c));
+ r.write (" };\n");
+ const char *fmt =
+ " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *expr */\n"
+ " %s, /* gcc_jit_block *default_block */\n"
+ " %i, /* int num_cases */\n"
+ " %s); /* gcc_jit_case **cases */\n";
+ r.write (fmt,
+ r.get_identifier (get_block ()),
+ r.get_identifier (get_loc ()),
+ r.get_identifier_as_rvalue (m_expr),
+ r.get_identifier (m_default_block),
+ m_cases.length (),
+ cases_id);
+}
+
} // namespace gcc::jit
} // namespace gcc
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index d3170fecb7c..acd69e9b78c 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -183,6 +183,11 @@ public:
rvalue *ptr,
rvalue *index);
+ case_ *
+ new_case (rvalue *min_value,
+ rvalue *max_value,
+ block *block);
+
void
set_str_option (enum gcc_jit_str_option opt,
const char *value);
@@ -196,6 +201,16 @@ public:
int value);
void
+ set_inner_bool_option (enum inner_bool_option inner_opt,
+ int value);
+
+ void
+ add_command_line_option (const char *optname);
+
+ void
+ append_command_line_options (vec <char *> *argvec);
+
+ void
enable_dump (const char *dumpname,
char **out_ptr);
@@ -217,6 +232,12 @@ public:
return m_bool_options[opt];
}
+ int
+ get_inner_bool_option (enum inner_bool_option opt) const
+ {
+ return m_inner_bool_options[opt];
+ }
+
result *
compile ();
@@ -260,6 +281,7 @@ private:
void log_str_option (enum gcc_jit_str_option opt) const;
void log_int_option (enum gcc_jit_int_option opt) const;
void log_bool_option (enum gcc_jit_bool_option opt) const;
+ void log_inner_bool_option (enum inner_bool_option opt) const;
void validate ();
@@ -281,6 +303,8 @@ private:
char *m_str_options[GCC_JIT_NUM_STR_OPTIONS];
int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS];
+ bool m_inner_bool_options[NUM_INNER_BOOL_OPTIONS];
+ auto_vec <char *> m_command_line_options;
/* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
auto_vec<requested_dump> m_requested_dumps;
@@ -935,6 +959,9 @@ public:
const char *
get_debug_string_parens (enum precedence outer_prec);
+ virtual bool is_constant () const { return false; }
+ virtual bool get_wide_int (wide_int *) const { return false; }
+
private:
virtual enum precedence get_precedence () const = 0;
@@ -1133,6 +1160,13 @@ public:
end_with_return (location *loc,
rvalue *rvalue);
+ statement *
+ end_with_switch (location *loc,
+ rvalue *expr,
+ block *default_block,
+ int num_cases,
+ case_ **cases);
+
playback::block *
playback_block () const
{
@@ -1148,7 +1182,7 @@ public:
statement *get_first_statement () const;
statement *get_last_statement () const;
- int get_successor_blocks (block **next1, block **next2) const;
+ vec <block *> get_successor_blocks () const;
private:
string * make_debug_string ();
@@ -1214,6 +1248,10 @@ public:
void visit_children (rvalue_visitor *) {}
+ bool is_constant () const { return true; }
+
+ bool get_wide_int (wide_int *out) const;
+
private:
string * make_debug_string ();
void write_reproducer (reproducer &r);
@@ -1577,8 +1615,7 @@ private:
class statement : public memento
{
public:
- virtual int get_successor_blocks (block **out_next1,
- block **out_next2) const;
+ virtual vec <block *> get_successor_blocks () const;
void write_to_dump (dump &d);
@@ -1702,8 +1739,7 @@ public:
void replay_into (replayer *r);
- int get_successor_blocks (block **out_next1,
- block **out_next2) const;
+ vec <block *> get_successor_blocks () const;
private:
string * make_debug_string ();
@@ -1726,8 +1762,7 @@ public:
void replay_into (replayer *r);
- int get_successor_blocks (block **out_next1,
- block **out_next2) const;
+ vec <block *> get_successor_blocks () const;
private:
string * make_debug_string ();
@@ -1748,8 +1783,7 @@ public:
void replay_into (replayer *r);
- int get_successor_blocks (block **out_next1,
- block **out_next2) const;
+ vec <block *> get_successor_blocks () const;
private:
string * make_debug_string ();
@@ -1759,6 +1793,60 @@ private:
rvalue *m_rvalue;
};
+class case_ : public memento
+{
+ public:
+ case_ (context *ctxt,
+ rvalue *min_value,
+ rvalue *max_value,
+ block *dest_block)
+ : memento (ctxt),
+ m_min_value (min_value),
+ m_max_value (max_value),
+ m_dest_block (dest_block)
+ {}
+
+ rvalue *get_min_value () const { return m_min_value; }
+ rvalue *get_max_value () const { return m_max_value; }
+ block *get_dest_block () const { return m_dest_block; }
+
+ void replay_into (replayer *) { /* empty */ }
+
+ void write_reproducer (reproducer &r);
+
+private:
+ string * make_debug_string ();
+
+ private:
+ rvalue *m_min_value;
+ rvalue *m_max_value;
+ block *m_dest_block;
+};
+
+class switch_ : public statement
+{
+public:
+ switch_ (block *b,
+ location *loc,
+ rvalue *expr,
+ block *default_block,
+ int num_cases,
+ case_ **cases);
+
+ void replay_into (replayer *r);
+
+ vec <block *> get_successor_blocks () const;
+
+private:
+ string * make_debug_string ();
+ void write_reproducer (reproducer &r);
+
+private:
+ rvalue *m_expr;
+ block *m_default_block;
+ auto_vec <case_ *> m_cases;
+};
+
} // namespace gcc::jit::recording
/* Create a recording::memento_of_new_rvalue_from_const instance and add
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index 62ef6a432ef..01579bd7312 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -45,6 +45,7 @@ namespace gccjit
class rvalue;
class lvalue;
class param;
+ class case_;
/* Errors within the API become C++ exceptions of this class. */
class error
@@ -120,6 +121,10 @@ namespace gccjit
void set_bool_option (enum gcc_jit_bool_option opt,
int value);
+ void set_bool_allow_unreachable_blocks (int bool_value);
+
+ void add_command_line_option (const char *optname);
+
location
new_location (const std::string &filename,
int line,
@@ -293,6 +298,10 @@ namespace gccjit
rvalue index,
location loc = location ());
+ case_ new_case (rvalue min_value,
+ rvalue max_value,
+ block dest_block);
+
private:
gcc_jit_context *m_inner_ctxt;
};
@@ -417,6 +426,10 @@ namespace gccjit
location loc = location ());
void end_with_return (location loc = location ());
+ void end_with_switch (rvalue expr,
+ block default_block,
+ std::vector <case_> cases,
+ location loc = location ());
};
class rvalue : public object
@@ -467,6 +480,14 @@ namespace gccjit
gcc_jit_param *get_inner_param () const;
};
+ class case_ : public object
+ {
+ public:
+ case_ ();
+ case_ (gcc_jit_case *inner);
+
+ gcc_jit_case *get_inner_case () const;
+ };
/* Overloaded operators, for those who want the most terse API
(at the possible risk of being a little too magical).
@@ -600,7 +621,19 @@ context::set_bool_option (enum gcc_jit_bool_option opt,
int value)
{
gcc_jit_context_set_bool_option (m_inner_ctxt, opt, value);
+}
+inline void
+context::set_bool_allow_unreachable_blocks (int bool_value)
+{
+ gcc_jit_context_set_bool_allow_unreachable_blocks (m_inner_ctxt,
+ bool_value);
+}
+
+inline void
+context::add_command_line_option (const char *optname)
+{
+ gcc_jit_context_add_command_line_option (m_inner_ctxt, optname);
}
inline location
@@ -1108,6 +1141,17 @@ context::new_array_access (rvalue ptr,
index.get_inner_rvalue ()));
}
+inline case_
+context::new_case (rvalue min_value,
+ rvalue max_value,
+ block dest_block)
+{
+ return case_ (gcc_jit_context_new_case (m_inner_ctxt,
+ min_value.get_inner_rvalue (),
+ max_value.get_inner_rvalue (),
+ dest_block.get_inner_block ()));
+}
+
// class object
inline context
object::get_context () const
@@ -1355,6 +1399,27 @@ block::end_with_return (location loc)
loc.get_inner_location ());
}
+inline void
+block::end_with_switch (rvalue expr,
+ block default_block,
+ std::vector <case_> cases,
+ location loc)
+{
+ /* Treat std::vector as an array, relying on it not being resized: */
+ case_ *as_array_of_wrappers = &cases[0];
+
+ /* Treat the array as being of the underlying pointers, relying on
+ the wrapper type being such a pointer internally. */
+ gcc_jit_case **as_array_of_ptrs =
+ reinterpret_cast<gcc_jit_case **> (as_array_of_wrappers);
+ gcc_jit_block_end_with_switch (get_inner_block (),
+ loc.get_inner_location (),
+ expr.get_inner_rvalue (),
+ default_block.get_inner_block (),
+ cases.size (),
+ as_array_of_ptrs);
+}
+
inline rvalue
block::add_call (function other,
location loc)
@@ -1545,6 +1610,20 @@ inline param::param (gcc_jit_param *inner)
: lvalue (gcc_jit_param_as_lvalue (inner))
{}
+// class case_ : public object
+inline case_::case_ () : object () {}
+inline case_::case_ (gcc_jit_case *inner)
+ : object (gcc_jit_case_as_object (inner))
+{
+}
+
+inline gcc_jit_case *
+case_::get_inner_case () const
+{
+ /* Manual downcast: */
+ return reinterpret_cast<gcc_jit_case *> (get_inner_object ());
+}
+
/* Overloaded operators. */
// Unary operators
inline rvalue operator- (rvalue a)
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index dedf942ebaa..4d7dd8cf40f 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "opts.h"
#include "safe-ctype.h"
+#include "typed-splay-tree.h"
#include "libgccjit.h"
#include "jit-common.h"
@@ -84,6 +85,10 @@ struct gcc_jit_param : public gcc::jit::recording::param
{
};
+struct gcc_jit_case : public gcc::jit::recording::case_
+{
+};
+
/**********************************************************************
Error-handling.
@@ -2123,6 +2128,382 @@ gcc_jit_block_end_with_void_return (gcc_jit_block *block,
block->end_with_return (loc, NULL);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_case method in
+ jit-recording.c. */
+
+gcc_jit_case *
+gcc_jit_context_new_case (gcc_jit_context *ctxt,
+ gcc_jit_rvalue *min_value,
+ gcc_jit_rvalue *max_value,
+ gcc_jit_block *block)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ RETURN_NULL_IF_FAIL (min_value, ctxt, NULL, "NULL min_value");
+ RETURN_NULL_IF_FAIL (max_value, ctxt, NULL, "NULL max_value");
+ RETURN_NULL_IF_FAIL (block, ctxt, NULL, "NULL block");
+
+ RETURN_NULL_IF_FAIL_PRINTF1 (min_value->is_constant (), ctxt, NULL,
+ "min_value is not a constant: %s",
+ min_value->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF1 (max_value->is_constant (), ctxt, NULL,
+ "max_value is not a constant: %s",
+ max_value->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ min_value->get_type ()->is_int (),
+ ctxt, NULL,
+ "min_value: %s (type: %s) is not of integer type",
+ min_value->get_debug_string (),
+ min_value->get_type ()->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ max_value->get_type ()->is_int (),
+ ctxt, NULL,
+ "max_value: %s (type: %s) is not of integer type",
+ max_value->get_debug_string (),
+ max_value->get_type ()->get_debug_string ());
+
+ wide_int wi_min, wi_max;
+ if (!min_value->get_wide_int (&wi_min))
+ gcc_unreachable ();
+ if (!max_value->get_wide_int (&wi_max))
+ gcc_unreachable ();
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ wi::les_p (wi_min, wi_max),
+ ctxt, NULL,
+ "min_value: %s > max_value: %s",
+ min_value->get_debug_string (),
+ max_value->get_debug_string ());
+ return (gcc_jit_case *)ctxt->new_case (min_value,
+ max_value,
+ block);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, this calls the trivial
+ gcc::jit::recording::memento::as_object method (a case is a
+ memento), in jit-recording.h. */
+
+gcc_jit_object *
+gcc_jit_case_as_object (gcc_jit_case *case_)
+{
+ RETURN_NULL_IF_FAIL (case_, NULL, NULL, "NULL case");
+
+ return static_cast <gcc_jit_object *> (case_->as_object ());
+}
+
+/* Helper function for gcc_jit_block_end_with_switch and
+ valid_case_for_switch. */
+
+static bool
+valid_dest_for_switch (gcc::jit::recording::context *ctxt,
+ gcc_jit_location *loc,
+ const char *api_funcname,
+ gcc::jit::recording::block *switch_block,
+ gcc::jit::recording::block *dest_block,
+ const char *dest_block_desc)
+{
+ if (!dest_block)
+ {
+ jit_error (ctxt, loc, "%s: NULL %s", api_funcname, dest_block_desc);
+ return false;
+ }
+ gcc::jit::recording::function *switch_fn = switch_block->get_function ();
+ gcc::jit::recording::function *dest_fn = dest_block->get_function ();
+ if (switch_fn != dest_fn)
+ {
+ jit_error (ctxt, loc,
+ "%s: %s is not in same function:"
+ " switch block %s is in function %s"
+ " whereas %s %s is in function %s",
+ api_funcname,
+ dest_block_desc,
+ switch_block->get_debug_string (),
+ switch_fn->get_debug_string (),
+ dest_block_desc,
+ dest_block->get_debug_string (),
+ dest_fn->get_debug_string ());
+ return false;
+ }
+ return true;
+}
+
+/* Helper function for gcc_jit_block_end_with_switch. */
+
+static bool
+valid_case_for_switch (gcc::jit::recording::context *ctxt,
+ gcc_jit_location *loc,
+ const char *api_funcname,
+ gcc_jit_block *switch_block,
+ gcc_jit_rvalue *expr,
+ gcc_jit_case *case_,
+ const char *case_desc,
+ int case_idx)
+{
+ if (!case_)
+ {
+ jit_error (ctxt, loc,
+ "%s:"
+ " NULL case %i",
+ api_funcname,
+ case_idx);
+ return false;
+ }
+ if (!valid_dest_for_switch (ctxt, loc,
+ api_funcname,
+ switch_block,
+ case_->get_dest_block (),
+ case_desc))
+ return false;
+ gcc::jit::recording::type *expr_type = expr->get_type ();
+ if (expr_type != case_->get_min_value ()->get_type ())
+ {
+ jit_error (ctxt, loc,
+ "%s:"
+ " mismatching types between case and expression:"
+ " cases[%i]->min_value: %s (type: %s)"
+ " expr: %s (type: %s)",
+ api_funcname,
+ case_idx,
+ case_->get_min_value ()->get_debug_string (),
+ case_->get_min_value ()->get_type ()->get_debug_string (),
+ expr->get_debug_string (),
+ expr_type->get_debug_string ());
+ return false;
+ }
+ if (expr_type != case_->get_max_value ()->get_type ())
+ {
+ jit_error (ctxt, loc,
+ "%s:"
+ " mismatching types between case and expression:"
+ " cases[%i]->max_value: %s (type: %s)"
+ " expr: %s (type: %s)",
+ api_funcname,
+ case_idx,
+ case_->get_max_value ()->get_debug_string (),
+ case_->get_max_value ()->get_type ()->get_debug_string (),
+ expr->get_debug_string (),
+ expr_type->get_debug_string ());
+ return false;
+ }
+ return true;
+}
+
+/* A class for holding the data we need to perform error-checking
+ on a libgccjit API call. */
+
+class api_call_validator
+{
+ public:
+ api_call_validator (gcc::jit::recording::context *ctxt,
+ gcc_jit_location *loc,
+ const char *funcname)
+ : m_ctxt (ctxt),
+ m_loc (loc),
+ m_funcname (funcname)
+ {}
+
+ protected:
+ gcc::jit::recording::context *m_ctxt;
+ gcc_jit_location *m_loc;
+ const char *m_funcname;
+};
+
+/* A class for verifying that the ranges of cases within
+ gcc_jit_block_end_with_switch don't overlap. */
+
+class case_range_validator : public api_call_validator
+{
+ public:
+ case_range_validator (gcc::jit::recording::context *ctxt,
+ gcc_jit_location *loc,
+ const char *funcname);
+
+ bool
+ validate (gcc_jit_case *case_, int idx);
+
+ private:
+ static int
+ case_compare (gcc::jit::recording::rvalue *k1,
+ gcc::jit::recording::rvalue *k2);
+
+ static wide_int
+ get_wide_int (gcc::jit::recording::rvalue *k);
+
+ private:
+ typed_splay_tree <gcc::jit::recording::rvalue *, gcc_jit_case *> m_cases;
+};
+
+/* case_range_validator's ctor. */
+
+case_range_validator::case_range_validator (gcc::jit::recording::context *ctxt,
+ gcc_jit_location *loc,
+ const char *funcname)
+: api_call_validator (ctxt, loc, funcname),
+ m_cases (case_compare, NULL, NULL)
+{
+}
+
+/* Ensure that the range of CASE_ does not overlap with any of the
+ ranges of cases we've already seen.
+ Return true if everything is OK.
+ Return false and emit an error if there is an overlap.
+ Compare with c-family/c-common.c:c_add_case_label. */
+
+bool
+case_range_validator::validate (gcc_jit_case *case_,
+ int case_idx)
+{
+ /* Look up the LOW_VALUE in the table of case labels we already
+ have. */
+ gcc_jit_case *other = m_cases.lookup (case_->get_min_value ());
+
+ /* If there was not an exact match, check for overlapping ranges. */
+ if (!other)
+ {
+ gcc_jit_case *pred;
+ gcc_jit_case *succ;
+
+ /* Even though there wasn't an exact match, there might be an
+ overlap between this case range and another case range.
+ Since we've (inductively) not allowed any overlapping case
+ ranges, we simply need to find the greatest low case label
+ that is smaller that CASE_MIN_VALUE, and the smallest low case
+ label that is greater than CASE_MAX_VALUE. If there is an overlap
+ it will occur in one of these two ranges. */
+ pred = m_cases.predecessor (case_->get_min_value ());
+ succ = m_cases.successor (case_->get_max_value ());
+
+ /* Check to see if the PRED overlaps. It is smaller than
+ the LOW_VALUE, so we only need to check its max value. */
+ if (pred)
+ {
+ wide_int wi_case_min = get_wide_int (case_->get_min_value ());
+ wide_int wi_pred_max = get_wide_int (pred->get_max_value ());
+ if (wi::ges_p (wi_pred_max, wi_case_min))
+ other = pred;
+ }
+
+ if (!other && succ)
+ {
+ /* Check to see if the SUCC overlaps. The low end of that
+ range is bigger than the low end of the current range. */
+ wide_int wi_case_max = get_wide_int (case_->get_max_value ());
+ wide_int wi_succ_min = get_wide_int (succ->get_min_value ());
+ if (wi::les_p (wi_succ_min, wi_case_max))
+ other = succ;
+ }
+ }
+
+ /* If there was an overlap, issue an error. */
+ if (other)
+ {
+ jit_error (m_ctxt, m_loc,
+ "%s: duplicate (or overlapping) cases values:"
+ " case %i: %s overlaps %s",
+ m_funcname,
+ case_idx,
+ case_->get_debug_string (),
+ other->get_debug_string ());
+ return false;
+ }
+
+ /* Register this case label in the splay tree. */
+ m_cases.insert (case_->get_min_value (),
+ case_);
+ return true;
+}
+
+/* Compare with c-family/c-common.c:case_compare, which acts on tree
+ nodes, rather than rvalue *.
+
+ Comparator for case label values. K1 and K2 must be constant integer
+ values (anything else should have been rejected by
+ gcc_jit_context_new_case.
+
+ Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after
+ K2, and 0 if K1 and K2 are equal. */
+
+int
+case_range_validator::case_compare (gcc::jit::recording::rvalue * k1,
+ gcc::jit::recording::rvalue * k2)
+{
+ wide_int wi1 = get_wide_int (k1);
+ wide_int wi2 = get_wide_int (k2);
+ return wi::cmps(wi1, wi2);
+}
+
+/* Given a const int rvalue K, get the underlying value as a wide_int. */
+
+wide_int
+case_range_validator::get_wide_int (gcc::jit::recording::rvalue *k)
+{
+ wide_int wi;
+ bool got_wi = k->get_wide_int (&wi);
+ gcc_assert (got_wi);
+ return wi;
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::block::end_with_switch method in
+ jit-recording.c. */
+
+void
+gcc_jit_block_end_with_switch (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *expr,
+ gcc_jit_block *default_block,
+ int num_cases,
+ gcc_jit_case **cases)
+{
+ RETURN_IF_NOT_VALID_BLOCK (block, loc);
+ gcc::jit::recording::context *ctxt = block->get_context ();
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_IF_FAIL (expr, ctxt, loc,
+ "NULL expr");
+ gcc::jit::recording::type *expr_type = expr->get_type ();
+ RETURN_IF_FAIL_PRINTF2 (
+ expr_type->is_int (),
+ ctxt, loc,
+ "expr: %s (type: %s) is not of integer type",
+ expr->get_debug_string (),
+ expr_type->get_debug_string ());
+ if (!valid_dest_for_switch (ctxt, loc,
+ __func__,
+ block,
+ default_block,
+ "default_block"))
+ return;
+ RETURN_IF_FAIL (num_cases >= 0, ctxt, loc, "num_cases < 0");
+ case_range_validator crv (ctxt, loc, __func__);
+ for (int i = 0; i < num_cases; i++)
+ {
+ char case_desc[32];
+ snprintf (case_desc, sizeof (case_desc),
+ "cases[%i]", i);
+ if (!valid_case_for_switch (ctxt, loc,
+ __func__,
+ block,
+ expr,
+ cases[i],
+ case_desc,
+ i))
+ return;
+ if (!crv.validate (cases[i], i))
+ return;
+ }
+
+ block->end_with_switch (loc, expr, default_block,
+ num_cases,
+ (gcc::jit::recording::case_ **)cases);
+}
+
/**********************************************************************
Option-management
**********************************************************************/
@@ -2185,6 +2566,42 @@ gcc_jit_context_set_bool_option (gcc_jit_context *ctxt,
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
+ gcc::jit::recording::context::set_inner_bool_option method in
+ jit-recording.c. */
+
+void
+gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt,
+ int bool_value)
+{
+ RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ ctxt->set_inner_bool_option (
+ gcc::jit::INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS,
+ bool_value);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::add_command_line_option method in
+ jit-recording.c. */
+
+void
+gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,
+ const char *optname)
+{
+ RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ RETURN_IF_FAIL (optname, ctxt, NULL, "NULL optname");
+ if (ctxt->get_logger ())
+ ctxt->get_logger ()->log ("optname: %s", optname);
+
+ ctxt->add_command_line_option (optname);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
gcc::jit::recording::context::enable_dump method in
jit-recording.c. */
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 8f4354eeeb5..32f2a5d3893 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -67,6 +67,7 @@ typedef struct gcc_jit_result gcc_jit_result;
+- gcc_jit_rvalue
+- gcc_jit_lvalue
+- gcc_jit_param
+ +- gcc_jit_case
*/
typedef struct gcc_jit_object gcc_jit_object;
@@ -131,6 +132,12 @@ typedef struct gcc_jit_lvalue gcc_jit_lvalue;
rvalue); use gcc_jit_param_as_lvalue to convert. */
typedef struct gcc_jit_param gcc_jit_param;
+/* A gcc_jit_case is for use when building multiway branches via
+ gcc_jit_block_end_with_switch and represents a range of integer
+ values (or an individual integer value) together with an associated
+ destination block. */
+typedef struct gcc_jit_case gcc_jit_case;
+
/* Acquire a JIT-compilation context. */
extern gcc_jit_context *
gcc_jit_context_acquire (void);
@@ -140,6 +147,9 @@ gcc_jit_context_acquire (void);
extern void
gcc_jit_context_release (gcc_jit_context *ctxt);
+/* Options present in the initial release of libgccjit.
+ These were handled using enums. */
+
/* Options taking string values. */
enum gcc_jit_str_option
{
@@ -243,6 +253,54 @@ gcc_jit_context_set_bool_option (gcc_jit_context *ctxt,
enum gcc_jit_bool_option opt,
int value);
+/* Options added after the initial release of libgccjit.
+ These are handled by providing an entrypoint per option,
+ rather than by extending the enum gcc_jit_*_option,
+ so that client code that use these new options can be identified
+ from binary metadata. */
+
+/* By default, libgccjit will issue an error about unreachable blocks
+ within a function.
+
+ This option can be used to disable that error.
+
+ This entrypoint was added in LIBGCCJIT_ABI_2; you can test for
+ its presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
+*/
+
+extern void
+gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt,
+ int bool_value);
+
+/* Pre-canned feature macro to indicate the presence of
+ gcc_jit_context_set_bool_allow_unreachable_blocks. This can be
+ tested for with #ifdef. */
+#define LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
+
+/* Add an arbitrary gcc command-line option to the context.
+ The context takes a copy of the string, so the
+ (const char *) optname is not needed anymore after the call
+ returns.
+
+ Note that only some options are likely to be meaningful; there is no
+ "frontend" within libgccjit, so typically only those affecting
+ optimization and code-generation are likely to be useful.
+
+ This entrypoint was added in LIBGCCJIT_ABI_1; you can test for
+ its presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
+*/
+
+extern void
+gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,
+ const char *optname);
+
+/* Pre-canned feature-test macro for detecting the presence of
+ gcc_jit_context_add_command_line_option within libgccjit.h. */
+
+#define LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
+
/* Compile the context to in-memory machine code.
This can be called more that once on a given context,
@@ -1046,6 +1104,81 @@ extern void
gcc_jit_block_end_with_void_return (gcc_jit_block *block,
gcc_jit_location *loc);
+/* Create a new gcc_jit_case instance for use in a switch statement.
+ min_value and max_value must be constants of integer type.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_3; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
+*/
+extern gcc_jit_case *
+gcc_jit_context_new_case (gcc_jit_context *ctxt,
+ gcc_jit_rvalue *min_value,
+ gcc_jit_rvalue *max_value,
+ gcc_jit_block *dest_block);
+
+/* Upcasting from case to object.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_3; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
+*/
+
+extern gcc_jit_object *
+gcc_jit_case_as_object (gcc_jit_case *case_);
+
+/* Terminate a block by adding evalation of an rvalue, then performing
+ a multiway branch.
+
+ This is roughly equivalent to this C code:
+
+ switch (expr)
+ {
+ default:
+ goto default_block;
+
+ case C0.min_value ... C0.max_value:
+ goto C0.dest_block;
+
+ case C1.min_value ... C1.max_value:
+ goto C1.dest_block;
+
+ ...etc...
+
+ case C[N - 1].min_value ... C[N - 1].max_value:
+ goto C[N - 1].dest_block;
+ }
+
+ block, expr, default_block and cases must all be non-NULL.
+
+ expr must be of the same integer type as all of the min_value
+ and max_value within the cases.
+
+ num_cases must be >= 0.
+
+ The ranges of the cases must not overlap (or have duplicate
+ values).
+
+ This API entrypoint was added in LIBGCCJIT_ABI_3; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
+*/
+
+extern void
+gcc_jit_block_end_with_switch (gcc_jit_block *block,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *expr,
+ gcc_jit_block *default_block,
+ int num_cases,
+ gcc_jit_case **cases);
+
+/* Pre-canned feature macro to indicate the presence of
+ gcc_jit_block_end_with_switch, gcc_jit_case_as_object, and
+ gcc_jit_context_new_case.
+
+ This can be tested for with #ifdef. */
+#define LIBGCCJIT_HAVE_SWITCH_STATEMENTS
+
/**********************************************************************
Nested contexts.
**********************************************************************/
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 89bd57be4f5..3c0a0c14a7a 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -17,6 +17,9 @@
# 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/>. */
+
+# The initial release of the library.
+LIBGCCJIT_ABI_0
{
global:
# Keep this list sorted alphabetically:
@@ -104,4 +107,24 @@
gcc_jit_type_get_volatile;
local: *;
-}; \ No newline at end of file
+};
+
+# Add support for adding arbitrary command-line options (PR jit/66628).
+LIBGCCJIT_ABI_1 {
+ global:
+ gcc_jit_context_add_command_line_option;
+} LIBGCCJIT_ABI_0;
+
+# Add support for disabling the check for unreachable blocks (PR jit/66546).
+LIBGCCJIT_ABI_2 {
+ global:
+ gcc_jit_context_set_bool_allow_unreachable_blocks;
+} LIBGCCJIT_ABI_1;
+
+# Add support for switch statements.
+LIBGCCJIT_ABI_3 {
+ global:
+ gcc_jit_block_end_with_switch;
+ gcc_jit_case_as_object;
+ gcc_jit_context_new_case;
+} LIBGCCJIT_ABI_2;
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 1d3f94e5ab0..75c2a77b3dc 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -4711,7 +4711,7 @@ inherit_reload_reg (bool def_p, int original_regno,
}
return false;
}
- lra_substitute_pseudo_within_insn (insn, original_regno, new_reg);
+ lra_substitute_pseudo_within_insn (insn, original_regno, new_reg, false);
lra_update_insn_regno_info (insn);
if (! def_p)
/* We now have a new usage insn for original regno. */
@@ -4743,7 +4743,7 @@ inherit_reload_reg (bool def_p, int original_regno,
lra_assert (DEBUG_INSN_P (usage_insn));
next_usage_insns = XEXP (next_usage_insns, 1);
}
- lra_substitute_pseudo (&usage_insn, original_regno, new_reg);
+ lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false);
lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn));
if (lra_dump_file != NULL)
{
@@ -5005,7 +5005,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
usage_insn = XEXP (next_usage_insns, 0);
lra_assert (DEBUG_INSN_P (usage_insn));
next_usage_insns = XEXP (next_usage_insns, 1);
- lra_substitute_pseudo (&usage_insn, original_regno, new_reg);
+ lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false);
lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn));
if (lra_dump_file != NULL)
{
@@ -5925,8 +5925,9 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
{
if (change_p && bitmap_bit_p (remove_pseudos, regno))
{
- lra_substitute_pseudo_within_insn (
- curr_insn, regno, regno_reg_rtx[restore_regno]);
+ lra_substitute_pseudo_within_insn
+ (curr_insn, regno, regno_reg_rtx[restore_regno],
+ false);
restored_regs_p = true;
}
else
@@ -6049,9 +6050,9 @@ undo_optional_reloads (void)
we remove the inheritance pseudo and the optional
reload. */
}
- lra_substitute_pseudo_within_insn (
- insn, regno,
- regno_reg_rtx[lra_reg_info[regno].restore_regno]);
+ lra_substitute_pseudo_within_insn
+ (insn, regno, regno_reg_rtx[lra_reg_info[regno].restore_regno],
+ false);
lra_update_insn_regno_info (insn);
if (lra_dump_file != NULL)
{
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 25bd3cefd81..e1d5ef2c918 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -358,8 +358,8 @@ extern void lra_update_dups (lra_insn_recog_data_t, signed char *);
extern void lra_process_new_insns (rtx_insn *, rtx_insn *, rtx_insn *,
const char *);
-extern bool lra_substitute_pseudo (rtx *, int, rtx);
-extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx);
+extern bool lra_substitute_pseudo (rtx *, int, rtx, bool);
+extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx, bool);
extern lra_insn_recog_data_t lra_set_insn_recog_data (rtx_insn *);
extern lra_insn_recog_data_t lra_update_insn_recog_data (rtx_insn *);
diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c
index 5157c85895e..88c0ef671b4 100644
--- a/gcc/lra-lives.c
+++ b/gcc/lra-lives.c
@@ -726,7 +726,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
{
insn = lra_insn_recog_data[uid]->insn;
lra_substitute_pseudo_within_insn (insn, dst_regno,
- SET_SRC (set));
+ SET_SRC (set), true);
lra_update_insn_regno_info (insn);
}
}
diff --git a/gcc/lra.c b/gcc/lra.c
index 5d1f429658f..bdd8e3ca3df 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -1777,9 +1777,10 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
/* Replace all references to register OLD_REGNO in *LOC with pseudo
- register NEW_REG. Return true if any change was made. */
+ register NEW_REG. Try to simplify subreg of constant if SUBREG_P.
+ Return true if any change was made. */
bool
-lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg)
+lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg, bool subreg_p)
{
rtx x = *loc;
bool result = false;
@@ -1791,9 +1792,25 @@ lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg)
return false;
code = GET_CODE (x);
- if (code == REG && (int) REGNO (x) == old_regno)
+ if (code == SUBREG && subreg_p)
{
- machine_mode mode = GET_MODE (*loc);
+ rtx subst, inner = SUBREG_REG (x);
+ /* Transform subreg of constant while we still have inner mode
+ of the subreg. The subreg internal should not be an insn
+ operand. */
+ if (REG_P (inner) && (int) REGNO (inner) == old_regno
+ && CONSTANT_P (new_reg)
+ && (subst = simplify_subreg (GET_MODE (x), new_reg, GET_MODE (inner),
+ SUBREG_BYTE (x))) != NULL_RTX)
+ {
+ *loc = subst;
+ return true;
+ }
+
+ }
+ else if (code == REG && (int) REGNO (x) == old_regno)
+ {
+ machine_mode mode = GET_MODE (x);
machine_mode inner_mode = GET_MODE (new_reg);
if (mode != inner_mode
@@ -1815,26 +1832,30 @@ lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg)
{
if (fmt[i] == 'e')
{
- if (lra_substitute_pseudo (&XEXP (x, i), old_regno, new_reg))
+ if (lra_substitute_pseudo (&XEXP (x, i), old_regno,
+ new_reg, subreg_p))
result = true;
}
else if (fmt[i] == 'E')
{
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno, new_reg))
+ if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno,
+ new_reg, subreg_p))
result = true;
}
}
return result;
}
-/* Call lra_substitute_pseudo within an insn. This won't update the insn ptr,
- just the contents of the insn. */
+/* Call lra_substitute_pseudo within an insn. Try to simplify subreg
+ of constant if SUBREG_P. This won't update the insn ptr, just the
+ contents of the insn. */
bool
-lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno, rtx new_reg)
+lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno,
+ rtx new_reg, bool subreg_p)
{
rtx loc = insn;
- return lra_substitute_pseudo (&loc, old_regno, new_reg);
+ return lra_substitute_pseudo (&loc, old_regno, new_reg, subreg_p);
}
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 15f5933d34f..254d7ba50b7 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -411,9 +411,9 @@ lto_write_tree (struct output_block *ob, tree expr, bool ref_p)
streamer_write_zero (ob);
}
-/* Emit the physical representation of tree node EXPR to output block
- OB. If THIS_REF_P is true, the leaves of EXPR are emitted as references
- via lto_output_tree_ref. REF_P is used for streaming siblings of EXPR. */
+/* Emit the physical representation of tree node EXPR to output block OB,
+ If THIS_REF_P is true, the leaves of EXPR are emitted as references via
+ lto_output_tree_ref. REF_P is used for streaming siblings of EXPR. */
static void
lto_output_tree_1 (struct output_block *ob, tree expr, hashval_t hash,
@@ -490,13 +490,20 @@ private:
tree expr, bool ref_p, bool this_ref_p);
hashval_t
- hash_scc (struct output_block *ob, unsigned first, unsigned size);
+ hash_scc (struct output_block *ob, unsigned first, unsigned size,
+ bool ref_p, bool this_ref_p);
hash_map<tree, sccs *> sccstate;
vec<worklist> worklist_vec;
struct obstack sccstate_obstack;
};
+/* Emit the physical representation of tree node EXPR to output block OB,
+ using depth-first search on the subgraph. If THIS_REF_P is true, the
+ leaves of EXPR are emitted as references via lto_output_tree_ref.
+ REF_P is used for streaming siblings of EXPR. If SINGLE_P is true,
+ this is for a rewalk of a single leaf SCC. */
+
DFS::DFS (struct output_block *ob, tree expr, bool ref_p, bool this_ref_p,
bool single_p)
{
@@ -564,7 +571,7 @@ DFS::DFS (struct output_block *ob, tree expr, bool ref_p, bool this_ref_p,
unsigned first, size;
tree x;
- /* If we are re-walking a single leaf-SCC just pop it,
+ /* If we are re-walking a single leaf SCC just pop it,
let earlier worklist item access the sccstack. */
if (single_p)
{
@@ -587,7 +594,7 @@ DFS::DFS (struct output_block *ob, tree expr, bool ref_p, bool this_ref_p,
unsigned scc_entry_len = 0;
if (!flag_wpa)
{
- scc_hash = hash_scc (ob, first, size);
+ scc_hash = hash_scc (ob, first, size, ref_p, this_ref_p);
/* Put the entries with the least number of collisions first. */
unsigned entry_start = 0;
@@ -1362,10 +1369,12 @@ DFS::scc_entry_compare (const void *p1_, const void *p2_)
return 0;
}
-/* Return a hash value for the SCC on the SCC stack from FIRST with SIZE. */
+/* Return a hash value for the SCC on the SCC stack from FIRST with SIZE.
+ THIS_REF_P and REF_P are as passed to lto_output_tree for FIRST. */
hashval_t
-DFS::hash_scc (struct output_block *ob, unsigned first, unsigned size)
+DFS::hash_scc (struct output_block *ob, unsigned first, unsigned size,
+ bool ref_p, bool this_ref_p)
{
unsigned int last_classes = 0, iterations = 0;
@@ -1441,7 +1450,8 @@ DFS::hash_scc (struct output_block *ob, unsigned first, unsigned size)
for (unsigned i = 0; i < size; ++i)
map.put (sccstack[first+i].t, sccstack[first+i].hash);
- DFS again (ob, sccstack[first+firstunique].t, false, false, true);
+ DFS again (ob, sccstack[first+firstunique].t, ref_p, this_ref_p,
+ true);
gcc_assert (again.sccstack.length () == size);
memcpy (sccstack.address () + first,
@@ -1539,9 +1549,9 @@ DFS::DFS_write_tree (struct output_block *ob, sccs *from_state,
}
-/* Emit the physical representation of tree node EXPR to output block
- OB. If THIS_REF_P is true, the leaves of EXPR are emitted as references
- via lto_output_tree_ref. REF_P is used for streaming siblings of EXPR. */
+/* Emit the physical representation of tree node EXPR to output block OB.
+ If THIS_REF_P is true, the leaves of EXPR are emitted as references via
+ lto_output_tree_ref. REF_P is used for streaming siblings of EXPR. */
void
lto_output_tree (struct output_block *ob, tree expr,
diff --git a/gcc/match-bitwise.pd b/gcc/match-bitwise.pd
index 88dd329785e..505025bfd80 100644
--- a/gcc/match-bitwise.pd
+++ b/gcc/match-bitwise.pd
@@ -18,87 +18,4 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-/* End of known transform origin. Note that some bitwise transforms
- are handled in match-constant-folding.pd. */
-
-/* ~x & ~y -> ~(x | y) */
-(simplify
- (bit_and (bit_not @0) (bit_not @1))
- (bit_not (bit_ior @0 @1)))
-
-/* ~x | ~y -> ~(x & y) */
-(simplify
- (bit_ior (bit_not @0) (bit_not @1))
- (bit_not (bit_and @0 @1)))
-
-/* Simple association cases that cancel one operand. */
-
-/* ((a OP b) & ~a) -> (b & ~a) OP 0 */
-(for bitop (bit_and bit_ior bit_xor)
- (simplify
- (bit_and:c (bitop:c @0 @1) (bit_not@2 @0))
- (bitop (bit_and @1 @2) { build_zero_cst (type); })))
-
-/* From fold-const.c:fold_binary_loc, in order of appearance. */
-
-/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
- with a constant, and the two constants have no bits in common,
- we should treat this as a BIT_IOR_EXPR since this may produce more
- simplifications. */
-(simplify
- (bit_xor (bit_and @0 INTEGER_CST@1) (bit_and @2 INTEGER_CST@3))
- (if (wi::bit_and (@1, @3) == 0)
- (bit_ior (bit_and @0 @1) (bit_and @2 @3))))
-
-/* ((a | b) ^ a) -> b & ~a */
-(simplify
- (bit_xor:c (bit_ior:c @0 @1) @0)
- (bit_and @1 (bit_not @0)))
-
-/* Convert ~X ^ ~Y to X ^ Y. */
-(simplify
- (bit_xor (bit_not @0) (bit_not @1))
- (bit_xor @0 @1))
-
-/* Convert ~X ^ C to X ^ ~C. */
-(simplify
- (bit_xor (bit_not @0) INTEGER_CST@1)
- (bit_xor @0 (bit_not @1)))
-
-/* Fold (X & 1) ^ 1 as (X & 1) == 0. */
-/* Questionable on GIMPLE as the equality compare can't have a
- type different from boolean_type_node. */
-
-/* Fold (X & Y) ^ Y as ~X & Y. */
-(simplify
- (bit_xor:c (bit_and:c @0 @1) @1)
- (bit_and (bit_not @0) @1))
-
-
-/* PR61559. Transforms for gcc.dg/builtin-bswap-8.c */
-(for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32 BUILT_IN_BSWAP64)
- (simplify
- (bswap (bswap @0))
- @0)
- (simplify
- (bswap (bit_not (bswap @0)))
- (bit_not @0))
- (for bitop (bit_xor bit_ior bit_and)
- /* This might not be profitable if the inner bswaps are
- free because @0 and @1 are memory operands and the
- target has an instruction for load+bswap. */
- (simplify
- (bitop (bswap @0) (bswap @1))
- (bswap (bitop @0 @1)))
- (simplify
- (bswap (bitop:c (bswap @0) @1))
- (bitop @0 (bswap @1)))))
-
-/* Similar transform for vector permute.
- ??? Missing an easy way to check if a mask is a reverse
- operation of another mask (most masks are not reversible). */
-(for bitop (bit_xor bit_ior bit_and)
- (simplify
- (bitop (vec_perm @1 @2 @0) (vec_perm @3 @4 @0))
- (vec_perm (bitop @1 @3) (bitop @2 @4) @0)))
diff --git a/gcc/match.pd b/gcc/match.pd
index 8804530a7db..59a0f99f941 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -238,6 +238,12 @@ along with GCC; see the file COPYING3. If not see
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(trunc_mod @0 (convert @1))))
+/* X - (X / Y) * Y is the same as X % Y. */
+(simplify
+ (minus (convert1? @0) (convert2? (mult (trunc_div @0 @1) @1)))
+ (if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+ (trunc_mod (convert @0) (convert @1))))
+
/* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
i.e. "X % C" into "X & (C - 1)", if X and C are positive.
Also optimize A % (C << N) where C is a power of 2,
@@ -277,6 +283,11 @@ along with GCC; see the file COPYING3. If not see
(bit_and @0 integer_zerop@1)
@1)
+/* ~x | x -> -1 */
+(simplify
+ (bit_ior:c (convert? @0) (convert? (bit_not @0)))
+ (convert { build_all_ones_cst (TREE_TYPE (@0)); }))
+
/* x ^ x -> 0 */
(simplify
(bit_xor @0 @0)
@@ -287,6 +298,11 @@ along with GCC; see the file COPYING3. If not see
(bit_xor @0 integer_all_onesp@1)
(bit_not @0))
+/* ~X ^ X is -1. */
+(simplify
+ (bit_xor:c (bit_not @0) @0)
+ { build_all_ones_cst (type); })
+
/* x & ~0 -> x */
(simplify
(bit_and @0 integer_all_onesp)
@@ -377,6 +393,55 @@ along with GCC; see the file COPYING3. If not see
(bit_and:c (bit_ior:c @0 @1) (bit_xor:c @1 (bit_not @0)))
(bit_and @0 @1))
+/* ~x & ~y -> ~(x | y)
+ ~x | ~y -> ~(x & y) */
+(for op (bit_and bit_ior)
+ rop (bit_ior bit_and)
+ (simplify
+ (op (convert1? (bit_not @0)) (convert2? (bit_not @1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+ (bit_not (rop (convert @0) (convert @1))))))
+
+/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
+ with a constant, and the two constants have no bits in common,
+ we should treat this as a BIT_IOR_EXPR since this may produce more
+ simplifications. */
+(simplify
+ (bit_xor (convert1? (bit_and@4 @0 INTEGER_CST@1))
+ (convert2? (bit_and@5 @2 INTEGER_CST@3)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && tree_nop_conversion_p (type, TREE_TYPE (@2))
+ && wi::bit_and (@1, @3) == 0)
+ (bit_ior (convert @4) (convert @5))))
+
+/* (X | Y) ^ X -> Y & ~ X*/
+(simplify
+ (bit_xor:c (convert? (bit_ior:c @0 @1)) (convert? @0))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (bit_and @1 (bit_not @0)))))
+
+/* Convert ~X ^ ~Y to X ^ Y. */
+(simplify
+ (bit_xor (convert1? (bit_not @0)) (convert2? (bit_not @1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+ (bit_xor (convert @0) (convert @1))))
+
+/* Convert ~X ^ C to X ^ ~C. */
+(simplify
+ (bit_xor (convert? (bit_not @0)) INTEGER_CST@1)
+ (bit_xor (convert @0) (bit_not @1)))
+
+/* Fold (X & Y) ^ Y as ~X & Y. */
+(simplify
+ (bit_xor:c (bit_and:c @0 @1) @1)
+ (bit_and (bit_not @0) @1))
+
+
+(simplify
+ (abs (abs@1 @0))
+ @1)
(simplify
(abs (negate @0))
(abs @0))
@@ -384,6 +449,24 @@ along with GCC; see the file COPYING3. If not see
(abs tree_expr_nonnegative_p@0)
@0)
+/* A - B -> A + (-B) if B is easily negatable. This just covers
+ very few cases of "easily negatable", effectively inlining negate_expr_p. */
+(simplify
+ (minus @0 INTEGER_CST@1)
+ (if ((INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type))
+ || (!TYPE_OVERFLOW_SANITIZED (type)
+ && may_negate_without_overflow_p (@1)))
+ (plus @0 (negate @1))))
+(simplify
+ (minus @0 REAL_CST@1)
+ (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
+ (plus @0 (negate @1))))
+(simplify
+ (minus @0 VECTOR_CST@1)
+ (if (FLOAT_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type))
+ (plus @0 (negate @1))))
+
/* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
when profitable.
@@ -415,6 +498,19 @@ along with GCC; see the file COPYING3. If not see
|| TYPE_PRECISION (type) != GET_MODE_PRECISION (TYPE_MODE (type))))
(convert (bitop @0 (convert @1))))))
+(for bitop (bit_and bit_ior)
+ rbitop (bit_ior bit_and)
+ /* (x | y) & x -> x */
+ /* (x & y) | x -> x */
+ (simplify
+ (bitop:c (rbitop:c @0 @1) @0)
+ @0)
+ /* (~x | y) & x -> x & y */
+ /* (~x & y) | x -> x | y */
+ (simplify
+ (bitop:c (rbitop:c (bit_not @0) @1) @0)
+ (bitop @0 @1)))
+
/* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
(for bitop (bit_and bit_ior bit_xor)
(simplify
@@ -462,19 +558,6 @@ along with GCC; see the file COPYING3. If not see
(op:c truth_valued_p@0 (logical_inverted_value @0))
{ constant_boolean_node (true, type); }))
-(for bitop (bit_and bit_ior)
- rbitop (bit_ior bit_and)
- /* (x | y) & x -> x */
- /* (x & y) | x -> x */
- (simplify
- (bitop:c (rbitop:c @0 @1) @0)
- @0)
- /* (~x | y) & x -> x & y */
- /* (~x & y) | x -> x | y */
- (simplify
- (bitop:c (rbitop:c (bit_not @0) @1) @0)
- (bitop @0 @1)))
-
/* If arg1 and arg2 are booleans (or any single bit type)
then try to simplify:
@@ -503,6 +586,32 @@ along with GCC; see the file COPYING3. If not see
(bit_not (bit_not @0))
@0)
+/* Convert ~ (-A) to A - 1. */
+(simplify
+ (bit_not (convert? (negate @0)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (minus @0 { build_one_cst (TREE_TYPE (@0)); }))))
+
+/* Convert ~ (A - 1) or ~ (A + -1) to -A. */
+(simplify
+ (bit_not (convert? (minus @0 integer_onep)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (negate @0))))
+(simplify
+ (bit_not (convert? (plus @0 integer_all_onesp)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (negate @0))))
+
+/* Part of convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */
+(simplify
+ (bit_not (convert? (bit_xor @0 INTEGER_CST@1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (bit_xor @0 (bit_not @1)))))
+(simplify
+ (bit_not (convert? (bit_xor:c (bit_not @0) @1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (bit_xor @0 @1))))
+
/* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */
(simplify
(bit_ior:c (bit_and:c@3 @0 (bit_not @2)) (bit_and:c@4 @1 @2))
@@ -1578,7 +1687,43 @@ along with GCC; see the file COPYING3. If not see
(convert (mult (convert:utype @0) (convert:utype @1))))))
-#include "match-bitwise.pd"
+/* Simple association cases that cancel one operand. */
+
+/* ((a OP b) & ~a) -> (b & ~a) OP 0 */
+(for bitop (bit_and bit_xor)
+ (simplify
+ (bit_and:c (bitop:c @0 @1) (bit_not@2 @0))
+ (bitop (bit_and @1 @2) { build_zero_cst (type); })))
+
+
+/* PR61559. Transforms for gcc.dg/builtin-bswap-8.c */
+(for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32 BUILT_IN_BSWAP64)
+ (simplify
+ (bswap (bswap @0))
+ @0)
+ (simplify
+ (bswap (bit_not (bswap @0)))
+ (bit_not @0))
+ (for bitop (bit_xor bit_ior bit_and)
+ /* This might not be profitable if the inner bswaps are
+ free because @0 and @1 are memory operands and the
+ target has an instruction for load+bswap. */
+ (simplify
+ (bitop (bswap @0) (bswap @1))
+ (bswap (bitop @0 @1)))
+ (simplify
+ (bswap (bitop:c (bswap @0) @1))
+ (bitop @0 (bswap @1)))))
+
+/* Similar transform for vector permute.
+ ??? Missing an easy way to check if a mask is a reverse
+ operation of another mask (most masks are not reversible). */
+(for bitop (bit_xor bit_ior bit_and)
+ (simplify
+ (bitop (vec_perm @1 @2 @0) (vec_perm @3 @4 @0))
+ (vec_perm (bitop @1 @3) (bitop @2 @4) @0)))
+
+
#include "match-builtin.pd"
#include "match-comparison.pd"
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 8218403f680..2e2070a7397 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -13425,12 +13425,54 @@ simd_clone_adjust (struct cgraph_node *node)
uniform args with __builtin_assume_aligned (arg_N(D), alignment)
lhs. Handle linear by adding PHIs. */
for (unsigned i = 0; i < node->simdclone->nargs; i++)
- if (node->simdclone->args[i].alignment
- && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
- && (node->simdclone->args[i].alignment
- & (node->simdclone->args[i].alignment - 1)) == 0
- && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
- == POINTER_TYPE)
+ if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
+ || !is_gimple_reg_type
+ (TREE_TYPE (node->simdclone->args[i].orig_arg))))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
+ iter1 = make_ssa_name (TREE_TYPE (orig_arg));
+ else
+ {
+ iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
+ gimple_add_tmp_var (iter1);
+ }
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (iter1, orig_arg);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (orig_arg, iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
+ && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
+ == REFERENCE_TYPE
+ && TREE_ADDRESSABLE
+ (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ tree def = ssa_default_def (cfun, orig_arg);
+ if (def && !has_zero_uses (def))
+ {
+ iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
+ gimple_add_tmp_var (iter1);
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (iter1, build_simple_mem_ref (def));
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (build_simple_mem_ref (def), iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ }
+ else if (node->simdclone->args[i].alignment
+ && node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && (node->simdclone->args[i].alignment
+ & (node->simdclone->args[i].alignment - 1)) == 0
+ && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
+ == POINTER_TYPE)
{
unsigned int alignment = node->simdclone->args[i].alignment;
tree orig_arg = node->simdclone->args[i].orig_arg;
@@ -13480,13 +13522,31 @@ simd_clone_adjust (struct cgraph_node *node)
== SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
{
tree orig_arg = node->simdclone->args[i].orig_arg;
- tree def = ssa_default_def (cfun, orig_arg);
gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
|| POINTER_TYPE_P (TREE_TYPE (orig_arg)));
- if (def && !has_zero_uses (def))
+ tree def = NULL_TREE;
+ if (TREE_ADDRESSABLE (orig_arg))
+ {
+ def = make_ssa_name (TREE_TYPE (orig_arg));
+ iter1 = make_ssa_name (TREE_TYPE (orig_arg));
+ iter2 = make_ssa_name (TREE_TYPE (orig_arg));
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (def, orig_arg);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else
+ {
+ def = ssa_default_def (cfun, orig_arg);
+ if (!def || has_zero_uses (def))
+ def = NULL_TREE;
+ else
+ {
+ iter1 = make_ssa_name (orig_arg);
+ iter2 = make_ssa_name (orig_arg);
+ }
+ }
+ if (def)
{
- iter1 = make_ssa_name (orig_arg);
- iter2 = make_ssa_name (orig_arg);
phi = create_phi_node (iter1, body_bb);
add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
@@ -13503,12 +13563,19 @@ simd_clone_adjust (struct cgraph_node *node)
imm_use_iterator iter;
use_operand_p use_p;
gimple use_stmt;
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
- if (use_stmt == phi)
- continue;
- else
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, iter1);
+ if (TREE_ADDRESSABLE (orig_arg))
+ {
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (orig_arg, iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
+ if (use_stmt == phi)
+ continue;
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, iter1);
}
}
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 8377c2267e6..5c761457fe9 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1110,7 +1110,7 @@ expand_doubleword_shift (machine_mode op1_mode, optab binoptab,
unsignedp, methods))
return false;
- emit_jump_insn (gen_jump (done_label));
+ emit_jump_insn (targetm.gen_jump (done_label));
emit_barrier ();
emit_label (subword_label);
@@ -2589,7 +2589,7 @@ expand_doubleword_clz (machine_mode mode, rtx op0, rtx target)
if (temp != result)
convert_move (result, temp, true);
- emit_jump_insn (gen_jump (after_label));
+ emit_jump_insn (targetm.gen_jump (after_label));
emit_barrier ();
/* Else clz of the full value is clz of the low word plus the number
@@ -5088,7 +5088,7 @@ expand_float (rtx to, rtx from, int unsignedp)
/* The sign bit is not set. Convert as signed. */
expand_float (target, from, 0);
- emit_jump_insn (gen_jump (label));
+ emit_jump_insn (targetm.gen_jump (label));
emit_barrier ();
/* The sign bit is set.
@@ -5293,7 +5293,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
/* If not, do the signed "fix" and branch around fixup code. */
expand_fix (to, from, 0);
- emit_jump_insn (gen_jump (lab2));
+ emit_jump_insn (targetm.gen_jump (lab2));
emit_barrier ();
/* Otherwise, subtract 2**(N-1), convert to signed number,
@@ -7575,12 +7575,12 @@ expand_asm_memory_barrier (void)
void
expand_mem_thread_fence (enum memmodel model)
{
- if (HAVE_mem_thread_fence)
- emit_insn (gen_mem_thread_fence (GEN_INT (model)));
+ if (targetm.have_mem_thread_fence ())
+ emit_insn (targetm.gen_mem_thread_fence (GEN_INT (model)));
else if (!is_mm_relaxed (model))
{
- if (HAVE_memory_barrier)
- emit_insn (gen_memory_barrier ());
+ if (targetm.have_memory_barrier ())
+ emit_insn (targetm.gen_memory_barrier ());
else if (synchronize_libfunc != NULL_RTX)
emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
else
@@ -7594,8 +7594,8 @@ expand_mem_thread_fence (enum memmodel model)
void
expand_mem_signal_fence (enum memmodel model)
{
- if (HAVE_mem_signal_fence)
- emit_insn (gen_mem_signal_fence (GEN_INT (model)));
+ if (targetm.have_mem_signal_fence ())
+ emit_insn (targetm.gen_mem_signal_fence (GEN_INT (model)));
else if (!is_mm_relaxed (model))
{
/* By default targets are coherent between a thread and the signal
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index 1ca3944d6ad..b14d381dc60 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,7 @@
+2015-06-29 Joseph Myers <joseph@codesourcery.com>
+
+ * sv.po: Update.
+
2015-06-22 Joseph Myers <joseph@codesourcery.com>
* sv.po: Update.
diff --git a/gcc/po/sv.po b/gcc/po/sv.po
index ad09346546c..adae8903aee 100644
--- a/gcc/po/sv.po
+++ b/gcc/po/sv.po
@@ -17,7 +17,7 @@ msgstr ""
"Project-Id-Version: gcc 5.1.0\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
"POT-Creation-Date: 2015-04-13 20:12+0000\n"
-"PO-Revision-Date: 2015-06-21 23:05+0200\n"
+"PO-Revision-Date: 2015-06-27 12:40+0200\n"
"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
@@ -48571,58 +48571,49 @@ msgid "Clause SEQ conflicts with INDEPENDENT at %L"
msgstr "Klausulen SEQ står i konflikt med INDEPENDENT vid %L"
#: fortran/openmp.c:4500
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s attribute conflicts with %s attribute at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause SEQ conflicts with GANG at %L"
-msgstr "%s-attribut i konflikt med %s-attribut vid %L"
+msgstr "Klausulen SEQ står i konflikt med GANG vid %L"
#: fortran/openmp.c:4502
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MOLD tag at %L conflicts with SOURCE tag at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause SEQ conflicts with WORKER at %L"
-msgstr "MOLD-taggen vid %L står i konflikt med SOURCE-taggen vid %L"
+msgstr "Klausulen SEQ står i konflikt med WORKER vid %L"
#: fortran/openmp.c:4504
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MOLD tag at %L conflicts with SOURCE tag at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause SEQ conflicts with VECTOR at %L"
-msgstr "MOLD-taggen vid %L står i konflikt med SOURCE-taggen vid %L"
+msgstr "Klausulen SEQ står i konflikt med VECTOR vid %L"
#: fortran/openmp.c:4506
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MOLD tag at %L conflicts with SOURCE tag at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause SEQ conflicts with AUTO at %L"
-msgstr "MOLD-taggen vid %L står i konflikt med SOURCE-taggen vid %L"
+msgstr "Klausulen SEQ står i konflikt med AUTO vid %L"
#: fortran/openmp.c:4511
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s attribute conflicts with %s attribute at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause AUTO conflicts with GANG at %L"
-msgstr "%s-attribut i konflikt med %s-attribut vid %L"
+msgstr "Klausulen AUTO står i konflikt med GANG vid %L"
#: fortran/openmp.c:4513
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MOLD tag at %L conflicts with SOURCE tag at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause AUTO conflicts with WORKER at %L"
-msgstr "MOLD-taggen vid %L står i konflikt med SOURCE-taggen vid %L"
+msgstr "Klausulen AUTO står i konflikt med WORKER vid %L"
#: fortran/openmp.c:4515
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MOLD tag at %L conflicts with SOURCE tag at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause AUTO conflicts with VECTOR at %L"
-msgstr "MOLD-taggen vid %L står i konflikt med SOURCE-taggen vid %L"
+msgstr "Klausulen AUTO står i konflikt med VECTOR vid %L"
#: fortran/openmp.c:4522
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MOLD tag at %L conflicts with SOURCE tag at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause GANG conflicts with WORKER at %L"
-msgstr "MOLD-taggen vid %L står i konflikt med SOURCE-taggen vid %L"
+msgstr "Klausulen GANG står i konflikt med WORKER vid %L"
#: fortran/openmp.c:4524
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MOLD tag at %L conflicts with SOURCE tag at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Clause GANG conflicts with VECTOR at %L"
-msgstr "MOLD-taggen vid %L står i konflikt med SOURCE-taggen vid %L"
+msgstr "Klausulen GANG står i konflikt med VECTOR vid %L"
#: fortran/openmp.c:4528
#, gcc-internal-format, gfc-internal-format
@@ -48635,22 +48626,19 @@ msgid "Tiled loop cannot be parallelized across gangs, workers and vectors at th
msgstr "Slinga uppdelad i bitar kan inte parallelliseras över gang, worker och vektorer på samma gång vid %L"
#: fortran/openmp.c:4556
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%qE is not a constant expression"
+#, gcc-internal-format, gfc-internal-format
msgid "TILE requires constant expression at %L"
-msgstr "%qE är inte ett konstant uttryck"
+msgstr "TILE behöver ett konstant uttryck vid %L"
#: fortran/openmp.c:4605
-#, fuzzy, gcc-internal-format
-#| msgid "sorry, unimplemented: "
+#, gcc-internal-format
msgid "Sorry, !$ACC cache unimplemented yet"
-msgstr "ledsen, inte implementerat: "
+msgstr "Ledsen, !$ACC-cache är fortfarande oimplementerat"
#: fortran/openmp.c:4627
-#, fuzzy, gcc-internal-format
-#| msgid "POINTER object '%s' in %s clause at %L"
+#, gcc-internal-format
msgid "PARAMETER object %qs is not allowed at %L"
-msgstr "POINTER-objekt ”%s” i %s-fall vid %L"
+msgstr "PARAMETER-objekt %qs är inte tillåtet vid %L"
#: fortran/openmp.c:4732
#, gcc-internal-format, gfc-internal-format
@@ -48713,58 +48701,49 @@ msgid "Reading file %qs as free form"
msgstr "Läser filen %qs som friform"
#: fortran/options.c:314
-#, fuzzy, gcc-internal-format
-#| msgid "'-fd-lines-as-comments' has no effect in free form"
+#, gcc-internal-format
msgid "%<-fd-lines-as-comments%> has no effect in free form"
-msgstr "”-fd-lines-as-comments” har ingen effekt i friform"
+msgstr "%<-fd-lines-as-comments%> har ingen effekt i friform"
#: fortran/options.c:317
-#, fuzzy, gcc-internal-format
-#| msgid "'-fd-lines-as-code' has no effect in free form"
+#, gcc-internal-format
msgid "%<-fd-lines-as-code%> has no effect in free form"
-msgstr "”-fd-lines-as-code” har ingen effekt i friform"
+msgstr "%<-fd-lines-as-code%> har ingen effekt i friform"
#: fortran/options.c:348
-#, fuzzy, gcc-internal-format
-#| msgid "Flag -fno-automatic overwrites -fmax-stack-var-size=%d"
+#, gcc-internal-format
msgid "Flag %<-fno-automatic%> overwrites %<-fmax-stack-var-size=%d%>"
-msgstr "Flaggan -fno-automatic åsidosätter -fmax-stack-var-size=%d"
+msgstr "Flaggan %<-fno-automatic%> åsidosätter %<-fmax-stack-var-size=%d%>"
#: fortran/options.c:351
-#, fuzzy, gcc-internal-format
-#| msgid "Flag -fno-automatic overwrites -frecursive"
+#, gcc-internal-format
msgid "Flag %<-fno-automatic%> overwrites %<-frecursive%>"
-msgstr "Flaggan -fno-automatic åsidosätter -frecursive"
+msgstr "Flaggan %<-fno-automatic%> åsidosätter %<-frecursive%>"
#: fortran/options.c:353
-#, fuzzy, gcc-internal-format
-#| msgid "Flag -fno-automatic overwrites -frecursive implied by -fopenmp"
+#, gcc-internal-format
msgid "Flag %<-fno-automatic%> overwrites %<-frecursive%> implied by %<-fopenmp%>"
-msgstr "Flaggan -fno-automatic åsidosätter -frecursive som impliceras av -fopenmp"
+msgstr "Flaggan %<-fno-automatic%> åsidosätter %<-frecursive%> som impliceras av %<-fopenmp%>"
#: fortran/options.c:356
-#, fuzzy, gcc-internal-format
-#| msgid "Flag -frecursive overwrites -fmax-stack-var-size=%d"
+#, gcc-internal-format
msgid "Flag %<-frecursive%> overwrites %<-fmax-stack-var-size=%d%>"
-msgstr "Flaggan -frecursive åsidosätter -fmax-stack-var-size=%d"
+msgstr "Flaggan %<-frecursive%> åsidosätter %<-fmax-stack-var-size=%d%>"
#: fortran/options.c:359
-#, fuzzy, gcc-internal-format
-#| msgid "Flag -fmax-stack-var-size=%d overwrites -frecursive implied by -fopenmp"
+#, gcc-internal-format
msgid "Flag %<-fmax-stack-var-size=%d%> overwrites %<-frecursive%> implied by %<-fopenmp%>"
-msgstr "Flaggan -fmax-stack-var-size=%d åsidosätter -frecursive som impliceras av -fopenmp"
+msgstr "Flaggan %<-fmax-stack-var-size=%d%> åsidosätter %<-frecursive%> som impliceras av %<-fopenmp%>"
#: fortran/options.c:391
-#, fuzzy, gcc-internal-format
-#| msgid "Fixed line length must be at least seven."
+#, gcc-internal-format
msgid "Fixed line length must be at least seven"
-msgstr "Fast radlängd måste vara minst sju."
+msgstr "Fast radlängd måste vara minst sju"
#: fortran/options.c:394
-#, fuzzy, gcc-internal-format
-#| msgid "Free line length must be at least three."
+#, gcc-internal-format
msgid "Free line length must be at least three"
-msgstr "Fri radlängd måste vara minst tre"
+msgstr "Fri radlängd måste vara minst tre."
#: fortran/options.c:397
#, gcc-internal-format, gfc-internal-format
@@ -48772,34 +48751,29 @@ msgid "Maximum subrecord length cannot exceed %d"
msgstr "Maximal delpostlängd får inte överstiga %d"
#: fortran/options.c:416
-#, fuzzy, gcc-internal-format
-#| msgid "gfortran: Only one -J option allowed"
+#, gcc-internal-format
msgid "gfortran: Only one %<-J%> option allowed"
-msgstr "gfortran: Endast en -J-flagga tillåts"
+msgstr "gfortran: Endast en %<-J%>-flagga tillåts"
#: fortran/options.c:488
-#, fuzzy, gcc-internal-format
-#| msgid "Argument to -ffpe-trap is not valid: %s"
+#, gcc-internal-format
msgid "Argument to %<-ffpe-trap%> is not valid: %s"
-msgstr "Argumentet till -ffpe-trap är inte giltigt: %s"
+msgstr "Argumentet till %<-ffpe-trap%> är inte giltigt: %s"
#: fortran/options.c:490
-#, fuzzy, gcc-internal-format
-#| msgid "Argument to -ffpe-summary is not valid: %s"
+#, gcc-internal-format
msgid "Argument to %<-ffpe-summary%> is not valid: %s"
-msgstr "Argumentet till -ffpe-summary är inte giltigt: %s"
+msgstr "Argumentet till %<-ffpe-summary%> är inte giltigt: %s"
#: fortran/options.c:530
-#, fuzzy, gcc-internal-format
-#| msgid "Argument to -fcheck is not valid: %s"
+#, gcc-internal-format
msgid "Argument to %<-fcheck%> is not valid: %s"
-msgstr "Argumentet till -fcheck är inte giltigt: %s"
+msgstr "Argumentet till %<-fcheck%> är inte giltigt: %s"
#: fortran/options.c:579
-#, fuzzy, gcc-internal-format
-#| msgid "-static-libgfortran is not supported in this configuration"
+#, gcc-internal-format
msgid "%<-static-libgfortran%> is not supported in this configuration"
-msgstr "-static-libgfortran stödjs inte i denna konfiguration"
+msgstr "%<-static-libgfortran%> stödjs inte i denna konfiguration"
#: fortran/options.c:602
#, gcc-internal-format, gfc-internal-format
@@ -48807,16 +48781,14 @@ msgid "Maximum supported identifier length is %d"
msgstr "Maximal stödd identifierarlängd är %d"
#: fortran/options.c:622
-#, fuzzy, gcc-internal-format
-#| msgid "Unrecognized option to -finit-logical: %s"
+#, gcc-internal-format
msgid "Unrecognized option to %<-finit-logical%>: %s"
-msgstr "Okänd argument till -finit-logical: %s"
+msgstr "Okänd argument till %<-finit-logical%>: %s"
#: fortran/options.c:638
-#, fuzzy, gcc-internal-format
-#| msgid "The value of n in -finit-character=n must be between 0 and 127"
+#, gcc-internal-format
msgid "The value of n in %<-finit-character=n%> must be between 0 and 127"
-msgstr "Värdet på n i -finit-character=n måste vara mellan 0 och 127"
+msgstr "Värdet på n i %<-finit-character=n%> måste vara mellan 0 och 127"
#: fortran/parse.c:556
#, gcc-internal-format, gfc-internal-format
@@ -48824,16 +48796,14 @@ msgid "Unclassifiable statement at %C"
msgstr "Oklassificerbar sats vid %C"
#: fortran/parse.c:600
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "OpenMP directives at %C may not appear in PURE or ELEMENTAL procedures"
+#, gcc-internal-format, gfc-internal-format
msgid "OpenACC directives at %C may not appear in PURE procedures"
-msgstr "OpenMP-direktiv vid %C för inte förekomma i PURE- eller ELEMENTAL-procedurer"
+msgstr "OpenACC-direktiv vid %C för inte förekomma i PURE-procedurer"
#: fortran/parse.c:665
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unclassifiable OpenMP directive at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "Unclassifiable OpenACC directive at %C"
-msgstr "Oklassificerbart OpenMP-direktiv vid %C"
+msgstr "Oklassificerbart OpenACC-direktiv vid %C"
#: fortran/parse.c:688
#, gcc-internal-format, gfc-internal-format
@@ -48886,10 +48856,9 @@ msgid "FORMAT statement at %L does not have a statement label"
msgstr "FORMAT-sats vid %L har inte en satsetikett"
#: fortran/parse.c:2147
-#, fuzzy, gcc-internal-format
-#| msgid "gfc_trans_code(): Bad statement code"
+#, gcc-internal-format
msgid "gfc_ascii_statement(): Bad statement code"
-msgstr "gfc_trans_code(): Felaktig satskod"
+msgstr "gfc_ascii_statement(): Felaktig satskod"
#: fortran/parse.c:2291
#, gcc-internal-format, gfc-internal-format
@@ -48897,10 +48866,9 @@ msgid "Unexpected %s statement at %C"
msgstr "Oväntad %s-sats vid %C"
#: fortran/parse.c:2428
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unexpected %s statement in MODULE at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "Unexpected %s statement in verify_st_order() at %C"
-msgstr "Oväntad %s-sats i MODULE vid %C"
+msgstr "Oväntad %s-sats i verify_st_order() vid %C"
#: fortran/parse.c:2439
#, gcc-internal-format, gfc-internal-format
@@ -49143,10 +49111,9 @@ msgid "End of nonblock DO statement at %C is interwoven with another DO loop"
msgstr "Slut på DO-sats utan block vid %C är sammanvävt med en annan DO-slinga"
#: fortran/parse.c:3824
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "CONTAINS block in derived type definition at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "CRITICAL block inside of OpenACC region at %C"
-msgstr "CONTAINS-block i härledd typdefinition vid %C"
+msgstr "CRITICAL-block i unuti OpenACC-region vid %C"
#: fortran/parse.c:3851
#, gcc-internal-format, gfc-internal-format
@@ -49179,28 +49146,24 @@ msgid "Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C"
msgstr "!$OMP END ATOMIC saknas efter !$OMP ATOMIC CAPTURE vid %C"
#: fortran/parse.c:4252 fortran/parse.c:4309
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Nested CRITICAL block at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "OpenACC directive inside of CRITICAL block at %C"
-msgstr "Nästade CRITICAL-block vid %C"
+msgstr "OpenACC-direktiv uniti CRITICAL-block vid %C"
#: fortran/parse.c:4285
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expecting %s statement at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Expecting %s at %C"
-msgstr "%s-sats förväntades vid %L"
+msgstr "%s förväntades vid %C"
#: fortran/parse.c:4328
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expected '(' at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "Expected DO loop at %C"
-msgstr "”(” förväntades vid %C"
+msgstr "DO-slinga förväntades vid %C"
#: fortran/parse.c:4348
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Redundant ACQUIRED_LOCK tag found at %L "
+#, gcc-internal-format, gfc-internal-format
msgid "Redundant !$ACC END LOOP at %C"
-msgstr "Överflödig ACQUIRED_LOCK-tagg funnen vid %L "
+msgstr "Överflödig !$ACC END LOOP vid %C"
#: fortran/parse.c:4561
#, gcc-internal-format, gfc-internal-format
@@ -49351,10 +49314,9 @@ msgid "exponent-letter 'q' in real-literal-constant at %C"
msgstr "exponentbokstav ”q” i reell literal konstant vid %C"
#: fortran/primary.c:562
-#, fuzzy, gcc-internal-format
-#| msgid "Extension: exponent-letter 'q' in real-literal-constant at %C"
+#, gcc-internal-format
msgid "Extension: exponent-letter %<q%> in real-literal-constant at %C"
-msgstr "Utökning: exponentbokstav ”q” i reeel literal konstant vid %C"
+msgstr "Utökning: exponentbokstav %<q%> i reeel literal konstant vid %C"
#: fortran/primary.c:578
#, gcc-internal-format, gfc-internal-format
@@ -49362,22 +49324,19 @@ msgid "Missing exponent in real number at %C"
msgstr "Exponent saknas i reellt tal vid %C"
#: fortran/primary.c:634
-#, fuzzy, gcc-internal-format
-#| msgid "Real number at %C has a 'd' exponent and an explicit kind"
+#, gcc-internal-format
msgid "Real number at %C has a %<d%> exponent and an explicit kind"
-msgstr "Reellt tal vid %C har en ”d”-exponent och en explicit sort"
+msgstr "Reellt tal vid %C har en %<d%>-exponent och en explicit sort"
#: fortran/primary.c:664
-#, fuzzy, gcc-internal-format
-#| msgid "Real number at %C has a 'q' exponent and an explicit kind"
+#, gcc-internal-format
msgid "Real number at %C has a %<q%> exponent and an explicit kind"
-msgstr "Reellt tal vid %C har en ”q”-exponent och en explicit sort"
+msgstr "Reellt tal vid %C har en %<q%>-exponent och en explicit sort"
#: fortran/primary.c:678
-#, fuzzy, gcc-internal-format
-#| msgid "Invalid exponent-letter 'q' in real-literal-constant at %C"
+#, gcc-internal-format
msgid "Invalid exponent-letter %<q%> in real-literal-constant at %C"
-msgstr "Ogiltig exponentbokstav ”q” i reell literal konstant vid %C"
+msgstr "Ogiltig exponentbokstav %<q%> i reell literal konstant vid %C"
#: fortran/primary.c:711
#, gcc-internal-format, gfc-internal-format
@@ -49510,10 +49469,9 @@ msgid "Symbol %qs at %C has no IMPLICIT type"
msgstr "Symbolen %qs vid %C har ingen IMPLICIT-typ"
#: fortran/primary.c:1926
-#, fuzzy, gcc-internal-format
-#| msgid "Unexpected '%%' for nonderived-type variable '%s' at %C"
+#, gcc-internal-format
msgid "Unexpected %<%%%> for nonderived-type variable %qs at %C"
-msgstr "Oväntat ”%%” för variabel med icke härled typ ”%s” vid %C"
+msgstr "Oväntat %<%%%> för variabel med icke härled typ %qs vid %C"
#: fortran/primary.c:1944
#, gcc-internal-format, gfc-internal-format
@@ -49536,16 +49494,14 @@ msgid "Coindexed procedure-pointer component at %C"
msgstr "Co-indexerad procedurpekarkomponent vid %C"
#: fortran/primary.c:2148
-#, fuzzy, gcc-internal-format
-#| msgid "variable symbol is not variable"
+#, gcc-internal-format
msgid "gfc_variable_attr(): Expression isn't a variable"
-msgstr "variabelsymbol är inte en variabel"
+msgstr "gfc_variable_attr(): Uttrycket är inte en variabel"
#: fortran/primary.c:2216
-#, fuzzy, gcc-internal-format
-#| msgid "creating array of references"
+#, gcc-internal-format
msgid "gfc_variable_attr(): Bad array reference"
-msgstr "skapar vektor av referenser"
+msgstr "gfc_variable_attr(): Felaktig vektorreferns"
#: fortran/primary.c:2386
#, gcc-internal-format, gfc-internal-format
@@ -49553,10 +49509,9 @@ msgid "Structure constructor with missing optional arguments at %C"
msgstr "Postkonstruerare med saknade valfria argument vid %C"
#: fortran/primary.c:2395
-#, fuzzy, gcc-internal-format
-#| msgid "No initializer for component '%s' given in the structure constructor at %C!"
+#, gcc-internal-format
msgid "No initializer for allocatable component '%qs' given in the structure constructor at %C"
-msgstr "Ingen initierare för komponent ”%s” angiven i postkonstrueraren vid %C!"
+msgstr "Ingen initierare för den allokerbara komponenten ”%qs” angiven i postkonstrueraren vid %C"
#: fortran/primary.c:2402
#, gcc-internal-format
@@ -49724,10 +49679,9 @@ msgid "Argument %qs of pure subroutine %qs at %L must have its INTENT specified
msgstr "Argumentet %qs till pure-subrutin %qs vid %L måste ha sitt INTENT angivet eller ha attributet VALUE"
#: fortran/resolve.c:421
-#, fuzzy, gcc-internal-format
-#| msgid "Argument '%s' of elemental procedure at %L must be scalar"
+#, gcc-internal-format
msgid "INTENT(OUT) argument '%s' of pure procedure %qs at %L may not be polymorphic"
-msgstr "”%s”-argumentet till elementär procedur vid %L måste vara skalärt"
+msgstr "INTENT(OUT)-argumentet ”%s” till den rena proceduren %qs vid %L får inte vara polymorf"
#: fortran/resolve.c:454
#, gcc-internal-format
@@ -49965,16 +49919,14 @@ msgid "%qs declared INTRINSIC at %L does not exist"
msgstr "%qs deklarerad INTRINSIC vid %L finns inte"
#: fortran/resolve.c:1698
-#, fuzzy, gcc-internal-format
-#| msgid "The intrinsic '%s' declared INTRINSIC at %L is not available in the current standard settings but %s. Use an appropriate -std=* option or enable -fall-intrinsics in order to use it."
+#, gcc-internal-format
msgid "The intrinsic %qs declared INTRINSIC at %L is not available in the current standard settings but %s. Use an appropriate %<-std=*%> option or enable %<-fall-intrinsics%> in order to use it."
-msgstr "Den inbyggda ”%s” deklarerad INTRINSIC vid %L är inte tillgänglig i den aktuella standardinställningen utan i %s. Använd en lämplig flagga -std=* eller aktivera -fall-intrinsics för att använda den."
+msgstr "Den inbyggda %qs deklarerad INTRINSIC vid %L är inte tillgänglig i den aktuella standardinställningen utan i %s. Använd en lämplig flagga %<-std=*%> eller aktivera %<-fall-intrinsics%> för att använda den."
#: fortran/resolve.c:1734
-#, fuzzy, gcc-internal-format
-#| msgid "Non-RECURSIVE procedure '%s' at %L is possibly calling itself recursively. Declare it RECURSIVE or use -frecursive"
+#, gcc-internal-format
msgid "Non-RECURSIVE procedure %qs at %L is possibly calling itself recursively. Declare it RECURSIVE or use %<-frecursive%>"
-msgstr "Icke RECURSIVE procedur ”%s” vid %L anropar kanske sig själv rekursivt. Deklarera den RECURSIVE eller använd -frecursive."
+msgstr "Icke RECURSIVE procedur %qs vid %L anropar kanske sig själv rekursivt. Deklarera den RECURSIVE eller använd %<-frecursive%>."
#: fortran/resolve.c:1773 fortran/resolve.c:8704 fortran/resolve.c:10199
#, gcc-internal-format, gfc-internal-format
@@ -50087,22 +50039,19 @@ msgid "Function %qs at %L has no IMPLICIT type"
msgstr "Funktionen %qs vid %L har ingen IMPLICIT-typ"
#: fortran/resolve.c:2845
-#, fuzzy, gcc-internal-format
-#| msgid "Reference to non-PURE function '%s' at %L inside a FORALL %s"
+#, gcc-internal-format
msgid "Reference to impure function %qs at %L inside a FORALL %s"
-msgstr "Referens till funktion ”%s” som inte är PURE vid %L är inuti ett FORALL-%s"
+msgstr "Referens till den orena funktionen %qs vid %L är inuti ett FORALL-%s"
#: fortran/resolve.c:2852
-#, fuzzy, gcc-internal-format
-#| msgid "Reference to non-PURE function '%s' at %L inside a DO CONCURRENT %s"
+#, gcc-internal-format
msgid "Reference to impure function %qs at %L inside a DO CONCURRENT %s"
-msgstr "Referens till funktion ”%s” som inte är PURE vid %L är inuti ett DO CONCURRENT-%s"
+msgstr "Referens till den orena funktionen %qs vid %L är inuti ett DO CONCURRENT-%s"
#: fortran/resolve.c:2859
-#, fuzzy, gcc-internal-format
-#| msgid "Reference to non-PURE function '%s' at %L inside a FORALL %s"
+#, gcc-internal-format
msgid "Reference to impure function %qs at %L within a PURE procedure"
-msgstr "Referens till funktion ”%s” som inte är PURE vid %L är inuti ett FORALL-%s"
+msgstr "Referens till den orena funktionen %qs vid %L inuti en PURE-procedur"
#: fortran/resolve.c:2922
#, gcc-internal-format
@@ -50121,10 +50070,9 @@ msgid "Function %qs is declared CHARACTER(*) and cannot be used at %L since it i
msgstr "Funktionen %qs är deklarerad CHARACTER(*) och får inte användas vid %L eftersom det inte är ett attrappargument"
#: fortran/resolve.c:3007
-#, fuzzy, gcc-internal-format
-#| msgid "<unresolved overloaded function type>"
+#, gcc-internal-format
msgid "resolve_function(): bad function type"
-msgstr "<ej upplöst överlagrad funktionstyp>"
+msgstr "resolve_function(): felaktig funktionstyp"
#: fortran/resolve.c:3027
#, gcc-internal-format
@@ -50192,10 +50140,9 @@ msgid "SUBROUTINE %qs at %L cannot be called recursively, as it is not RECURSIVE
msgstr "SUBROUTINE %qs vid %L får inte anropas rekursivt, eftersom den inte är RECURSIVE"
#: fortran/resolve.c:3459
-#, fuzzy, gcc-internal-format
-#| msgid "<unresolved overloaded function type>"
+#, gcc-internal-format
msgid "resolve_subroutine(): bad function type"
-msgstr "<ej upplöst överlagrad funktionstyp>"
+msgstr "resolve_subroutine(): felaktig funktionstyp"
#: fortran/resolve.c:3497
#, gcc-internal-format, gfc-internal-format
@@ -50258,10 +50205,9 @@ msgid "Upper array reference at %L is out of bounds (%ld > %ld) in dimension %d"
msgstr "Övre vektorreferens vid %L är utanför gränsen (%ld > %ld) i dimension %d"
#: fortran/resolve.c:4123
-#, fuzzy, gcc-internal-format
-#| msgid "subscript missing in array reference"
+#, gcc-internal-format
msgid "check_dimension(): Bad array reference"
-msgstr "index saknas i vektorreferens"
+msgstr "check_dimension(): Felaktig vektorreferens"
#: fortran/resolve.c:4146
#, gcc-internal-format, gfc-internal-format
@@ -50364,10 +50310,9 @@ msgid "Substring end index at %L is too large"
msgstr "Slutindex för delsträng vid %L är för stort"
#: fortran/resolve.c:4668
-#, fuzzy, gcc-internal-format
-#| msgid "Bad array reference at %L"
+#, gcc-internal-format
msgid "resolve_ref(): Bad array reference"
-msgstr "Felaktig vektorreferens vid %L"
+msgstr "resolve_ref(): Felaktig vektorreferens"
#: fortran/resolve.c:4682
#, gcc-internal-format, gfc-internal-format
@@ -50494,10 +50439,9 @@ msgid "%qs at %L should be a FUNCTION"
msgstr "%qs vid %L skulle vara en SUBROUTINE"
#: fortran/resolve.c:6321
-#, fuzzy, gcc-internal-format
-#| msgid "Expected expression type"
+#, gcc-internal-format
msgid "gfc_resolve_expr(): Bad expression type"
-msgstr "Uttryckstyp förväntades"
+msgstr "gfc_resolve_expr(): Felaktig uttryckstyp"
#: fortran/resolve.c:6347
#, gcc-internal-format, gfc-internal-format
@@ -50520,10 +50464,9 @@ msgid "Step expression in DO loop at %L cannot be zero"
msgstr "Steguttryck i DO-slinga vid %L får inte vara noll"
#: fortran/resolve.c:6446
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "DO loop at %L will be executed zero times (use -Wno-zerotrip to suppress)"
+#, gcc-internal-format, gfc-internal-format
msgid "DO loop at %L will be executed zero times"
-msgstr "DO-slinga vid %L kommer köras noll gånger (använd -Wno-zerotrip för att undertrycka)"
+msgstr "DO-slinga vid %L kommer köras noll gånger"
#: fortran/resolve.c:6507
#, gcc-internal-format, gfc-internal-format
@@ -50951,10 +50894,9 @@ msgid "Assignment to an allocatable polymorphic variable at %L"
msgstr "Tilldelning till en allokerbar polymorf variabel vid %L"
#: fortran/resolve.c:9453
-#, fuzzy, gcc-internal-format
-#| msgid "Assignment to an allocatable polymorphic variable at %L requires -frealloc-lhs"
+#, gcc-internal-format
msgid "Assignment to an allocatable polymorphic variable at %L requires %<-frealloc-lhs%>"
-msgstr "Tilldelning till en allokerbar polymorf variabel vid %L kräver -frealloc-lhs"
+msgstr "Tilldelning till en allokerbar polymorf variabel vid %L kräver %<-frealloc-lhs%>"
#. See PR 43366.
#: fortran/resolve.c:9458
@@ -50968,8 +50910,7 @@ msgid "Nonallocatable variable must not be polymorphic in intrinsic assignment a
msgstr "Ej allokerbar variabel får inte vara polymorf i inbyggd tilldelning vid %L - kontrollera att det finns en matchande specifik subrutin för operatorn ”=”"
#: fortran/resolve.c:9475
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Coindexed variable must not be have an allocatable ultimate component in assignment at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Coindexed variable must not have an allocatable ultimate component in assignment at %L"
msgstr "Co-indexerad variabel får inte ha en allokerbar yttersta komponent i tilldelningen vid %L"
@@ -51019,10 +50960,9 @@ msgid "FORALL mask clause at %L requires a scalar LOGICAL expression"
msgstr "FORALL-maskklausul vid %L kräver ett skalärt LOGICAL-uttryck"
#: fortran/resolve.c:10453
-#, fuzzy, gcc-internal-format
-#| msgid "gfc_trans_code(): Bad statement code"
+#, gcc-internal-format
msgid "gfc_resolve_code(): Bad statement code"
-msgstr "gfc_trans_code(): Felaktig satskod"
+msgstr "gfc_resolve_code(): Felaktig satskod"
#: fortran/resolve.c:10548
#, gcc-internal-format, gfc-internal-format
@@ -51929,10 +51869,9 @@ msgid "%qs is not a directory"
msgstr "%qs är inte en katalog"
#: fortran/scanner.c:742
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "!$OMP at %C starts a commented line as it neither is followed by a space nor is a continuation line"
+#, gcc-internal-format, gfc-internal-format
msgid "!$ACC at %C starts a commented line as it neither is followed by a space nor is a continuation line"
-msgstr "!$OMP vid %C inleder en kommentarrad eftersom det varken följs av en blank eller en fortsättningsrad"
+msgstr "!$ACC vid %C inleder en kommentarrad eftersom det varken följs av en blank eller en fortsättningsrad"
#: fortran/scanner.c:782
#, gcc-internal-format, gfc-internal-format
@@ -51950,10 +51889,9 @@ msgid "Limit of %d continuations exceeded in statement at %C"
msgstr "Gränsen på %d fortsättningar överskrids i sats vid %C"
#: fortran/scanner.c:1392
-#, fuzzy, gcc-internal-format
-#| msgid "Missing '&' in continued character constant at %C"
+#, gcc-internal-format
msgid "Missing %<&%> in continued character constant at %C"
-msgstr "”&” saknas i fortsatt teckenkonstant vid %C"
+msgstr "%<&%> saknas i fortsatt teckenkonstant vid %C"
#: fortran/scanner.c:1642
#, gcc-internal-format, gfc-internal-format
@@ -51961,10 +51899,9 @@ msgid "Nonconforming tab character at %C"
msgstr "Ej konformt tabulatortecken vid %C"
#: fortran/scanner.c:1730 fortran/scanner.c:1733
-#, fuzzy, gcc-internal-format
-#| msgid "'&' not allowed by itself in line %d"
+#, gcc-internal-format
msgid "%<&%> not allowed by itself in line %d"
-msgstr "”&” är inte tillåtet ensamt på rad %d"
+msgstr "%<&%> är inte tillåtet ensamt på rad %d"
#: fortran/scanner.c:1792
#, gcc-internal-format, gfc-internal-format
@@ -52210,10 +52147,9 @@ msgid "Second argument of MOD at %L is zero"
msgstr "Andra argumentet till MOD vid %L är noll"
#: fortran/simplify.c:4370
-#, fuzzy, gcc-internal-format
-#| msgid "gfc_trans_code(): Bad statement code"
+#, gcc-internal-format
msgid "gfc_simplify_mod(): Bad arguments"
-msgstr "gfc_trans_code(): Felaktig satskod"
+msgstr "gfc_simplify_mod(): Felaktiga argument"
#. Result is processor-dependent. This processor just opts
#. to not handle it at all.
@@ -52244,10 +52180,9 @@ msgid "Argument NCOPIES of REPEAT intrinsic is too large at %L"
msgstr "Argumentet NCOPIES till inbyggd REPEAT är för stort vid %L"
#: fortran/simplify.c:5169
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Integer too large at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "Reshaped array too large at %C"
-msgstr "För stort heltal vid %C"
+msgstr "Omformad vektor är för stor vid %C"
#: fortran/simplify.c:5280
#, gcc-internal-format, gfc-internal-format
@@ -52255,10 +52190,9 @@ msgid "Result of SCALE overflows its kind at %L"
msgstr "Resultat av SCALE spiller över sin sort vid %L"
#: fortran/simplify.c:5940
-#, fuzzy, gcc-internal-format
-#| msgid "Bad type in constant expression"
+#, gcc-internal-format
msgid "Bad type in gfc_simplify_sign"
-msgstr "Felaktig typ i konstant uttryck"
+msgstr "Felaktig typ i gfc_simplify_sign"
#: fortran/simplify.c:5969
#, gcc-internal-format
@@ -52276,10 +52210,9 @@ msgid "Argument of SQRT at %L has a negative value"
msgstr "Argument till SQRT vid %L har ett negativt värde"
#: fortran/simplify.c:6200
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "invalid argument of %qE attribute"
+#, gcc-internal-format, gfc-internal-format
msgid "invalid argument of SQRT at %L"
-msgstr "ogiltigt argument till attributet %qE"
+msgstr "ogiltigt argument till SQRT vid %L"
#: fortran/simplify.c:6495
#, gcc-internal-format, gfc-internal-format
@@ -52292,10 +52225,9 @@ msgid "Out of bounds in IMAGE_INDEX at %L for dimension %d, SUB has %ld and COAR
msgstr "Utanför gränserna i IMAGE_INDEX vid %L för dimension %d, SUB har %ld och COARRAY övre gräns är %ld)"
#: fortran/simplify.c:6853
-#, fuzzy, gcc-internal-format
-#| msgid "gfc_conv_constant_to_tree(): invalid type: %s"
+#, gcc-internal-format
msgid "gfc_convert_constant(): Unexpected type"
-msgstr "gfc_conv_constant_to_tree(): ogiltig typ: %s"
+msgstr "gfc_convert_constant(): Oväntad typ"
#: fortran/simplify.c:6939
#, gcc-internal-format
@@ -52303,22 +52235,19 @@ msgid "Character %qs in string at %L cannot be converted into character kind %d"
msgstr "Tecknet %qs i sträng vid %L kan inte konverteras till tecken av sort %d"
#: fortran/st.c:254
-#, fuzzy, gcc-internal-format
-#| msgid "gfc_trans_code(): Bad statement code"
+#, gcc-internal-format
msgid "gfc_free_statement(): Bad statement"
-msgstr "gfc_trans_code(): Felaktig satskod"
+msgstr "gfc_free_statement(): Felaktig sats"
#: fortran/symbol.c:131
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "SAVE statement at %C follows blanket SAVE statement"
+#, gcc-internal-format, gfc-internal-format
msgid "IMPLICIT NONE (type) statement at %L following an IMPLICIT statement"
-msgstr "SAVE-sats vid %C följer allmän SAVE-sats"
+msgstr "IMPLICIT NONE (type)-sats vid %L följer en IMPLICIT-sats"
#: fortran/symbol.c:168
-#, fuzzy, gcc-internal-format
-#| msgid "Letter '%c' already set in IMPLICIT statement at %C"
+#, gcc-internal-format
msgid "Letter %<%c%> already set in IMPLICIT statement at %C"
-msgstr "Tecknet ”%c” redan satt i IMPLICIT-sats vid %C"
+msgstr "Tecknet %<%c%> redan satt i IMPLICIT-sats vid %C"
#: fortran/symbol.c:190
#, gcc-internal-format, gfc-internal-format
@@ -52691,10 +52620,9 @@ msgid "Symbol %qs is used before it is typed at %L"
msgstr "Symbolen %qs används före den har fått sin typ vid %L"
#: fortran/target-memory.c:136
-#, fuzzy, gcc-internal-format
-#| msgid "invalid expression for min lvalue"
+#, gcc-internal-format
msgid "Invalid expression in gfc_element_size."
-msgstr "ogiltigt uttryck som min-l-värde"
+msgstr "Ogiltigt uttryck i gfc_element_size."
#: fortran/target-memory.c:356
#, gcc-internal-format
@@ -52719,10 +52647,9 @@ msgstr "BOZ-konstant vid %L är för stor (%ld jämfört med %ld bitar)"
#. Problems occur when we get something like
#. integer :: a(lots) = (/(i, i=1, lots)/)
#: fortran/trans-array.c:5482
-#, fuzzy, gcc-internal-format
-#| msgid "The number of elements in the array constructor at %L requires an increase of the allowed %d upper limit. See -fmax-array-constructor option"
+#, gcc-internal-format
msgid "The number of elements in the array constructor at %L requires an increase of the allowed %d upper limit. See %<-fmax-array-constructor%> option"
-msgstr "Antalet element i vektorkonstrueraren vid %L kräver en ökning av den tillåtna övre gränsen %d. Se flaggan -fmax-array-constructor"
+msgstr "Antalet element i vektorkonstrueraren vid %L kräver en ökning av den tillåtna övre gränsen %d. Se flaggan %<-fmax-array-constructor%>"
#: fortran/trans-array.c:7263
#, gcc-internal-format
@@ -52740,10 +52667,9 @@ msgid "Named COMMON block %qs at %L shall be of the same size as elsewhere (%lu
msgstr "Namngivet COMMON-block %qs vid %L skall ha samma storlek som på andra håll (%lu mot %lu byte)"
#: fortran/trans-common.c:783
-#, fuzzy, gcc-internal-format
-#| msgid "requested position is not an integer constant"
+#, gcc-internal-format
msgid "get_mpz(): Not an integer constant"
-msgstr "den begärda positionen är inte en heltalskonstant"
+msgstr "get_mpz(): Inte en heltalskonstant"
#: fortran/trans-common.c:811
#, gcc-internal-format
@@ -52797,16 +52723,14 @@ msgid "COMMON '%s' at %L does not exist"
msgstr "COMMON ”%s” vid %L existerar inte"
#: fortran/trans-common.c:1186
-#, fuzzy, gcc-internal-format
-#| msgid "COMMON '%s' at %L requires %d bytes of padding; reorder elements or use -fno-align-commons"
+#, gcc-internal-format
msgid "COMMON %qs at %L requires %d bytes of padding; reorder elements or use %<-fno-align-commons%>"
-msgstr "COMMON ”%s” vid %L kräver %d byte utfyllnad, byt ordning på element eller använd -fno-align-commons"
+msgstr "COMMON %qs vid %L kräver %d byte utfyllnad, byt ordning på element eller använd %<-fno-align-commons%>"
#: fortran/trans-common.c:1191
-#, fuzzy, gcc-internal-format
-#| msgid "COMMON at %L requires %d bytes of padding; reorder elements or use -fno-align-commons"
+#, gcc-internal-format
msgid "COMMON at %L requires %d bytes of padding; reorder elements or use %<-fno-align-commons%>"
-msgstr "COMMON vid %L kräver %d byte utfyllnad, byt ordning på element eller använd -fno-align-commons"
+msgstr "COMMON vid %L kräver %d byte utfyllnad, byt ordning på element eller använd %<-fno-align-commons%>"
#: fortran/trans-const.c:335
#, gcc-internal-format, gfc-internal-format
@@ -52839,10 +52763,9 @@ msgid "Deferred type parameter not yet supported"
msgstr "Fördröjd typparameter stödjs inte ännu"
#: fortran/trans-decl.c:4489
-#, fuzzy, gcc-internal-format
-#| msgid "backend decl for module variable %s already exists"
+#, gcc-internal-format
msgid "backend decl for module variable %qs already exists"
-msgstr "bakändedeklaration för modulvariabel %s finns redan"
+msgstr "bakändedeklaration för modulvariabel %qs finns redan"
#: fortran/trans-decl.c:4502
#, gcc-internal-format
@@ -52905,16 +52828,14 @@ msgid "Code for reallocating the allocatable variable at %L will be added"
msgstr "Kod för omallokering av den allokerbara variabeln vid %L kommer läggas till"
#: fortran/trans-expr.c:1708
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assignment to an allocatable polymorphic variable at %L is not yet supported"
+#, gcc-internal-format, gfc-internal-format
msgid "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at %L is not yet supported"
-msgstr "Tilldelning till allokerbar polymorf variabel vid %L stödjs inte ännu"
+msgstr "Ledsen, co-indexerad åtkomst till en pekar- eller allokerbar komponent av den co-indexerade co-vektorn vid %L stödjs inte ännu"
#: fortran/trans-expr.c:1722
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Support for the A argument at %L with allocatable components is not yet implemented"
+#, gcc-internal-format, gfc-internal-format
msgid "Sorry, coindexed coarray at %L with allocatable component is not yet supported"
-msgstr "Stöd för argumentet A vid %L med allokerbara komponenter är inte implementerat ännu"
+msgstr "Ledsen, co-indexerad co-vektor vid %L med allokerbara komponenter är inte implementerat ännu"
#: fortran/trans-expr.c:1745
#, gcc-internal-format, gfc-internal-format
@@ -52932,23 +52853,20 @@ msgid "Unknown argument list function at %L"
msgstr "Okänd argumentlistefunktion vid %L"
#: fortran/trans-intrinsic.c:869
-#, fuzzy, gcc-internal-format
-#| msgid "Intrinsic function %s(%d) not recognized"
+#, gcc-internal-format
msgid "Intrinsic function %qs (%d) not recognized"
-msgstr "Inbyggd funktion %s(%d) känns inte igen"
+msgstr "Inbyggd funktion %qs (%d) känns inte igen"
#: fortran/trans-intrinsic.c:1487 fortran/trans-intrinsic.c:1873
#: fortran/trans-intrinsic.c:2069
-#, fuzzy, gcc-internal-format
-#| msgid "'dim' argument of %s intrinsic at %L is not a valid dimension index"
+#, gcc-internal-format
msgid "%<dim%> argument of %s intrinsic at %L is not a valid dimension index"
-msgstr "”dim”-argumentet till inbyggd ”%s” vid %L är inte ett giltigt dimensionsindex"
+msgstr "%<dim%>-argumentet till inbyggd %s vid %L är inte ett giltigt dimensionsindex"
#: fortran/trans-io.c:1861
-#, fuzzy, gcc-internal-format
-#| msgid "Internal file at %L with namelist"
+#, gcc-internal-format
msgid "build_dt: format with namelist"
-msgstr "Intern fil vid %L med namnlista"
+msgstr "build_dt: format med namnlista"
#: fortran/trans-io.c:2265
#, gcc-internal-format, gfc-internal-format
@@ -52966,10 +52884,9 @@ msgid "An alternate return at %L without a * dummy argument"
msgstr "En alternativ retur vid %L utan ett * attrappargument"
#: fortran/trans-stmt.c:729
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Deferred-length character component '%s' at %L is not yet supported"
+#, gcc-internal-format, gfc-internal-format
msgid "Sorry, the lock component of derived type at %L is not yet supported"
-msgstr "Teckenkomponenten ”%s” med fördröjd längd vid %L stödjs inte ännu"
+msgstr "Ledsen, låskomponenten hos härledd typ vid %L stödjs inte ännu"
#: fortran/trans-stmt.c:994
#, gcc-internal-format, gfc-internal-format
@@ -52977,70 +52894,59 @@ msgid "Sorry, only support for integer kind %d implemented for image-set at %L"
msgstr "Tyvärr, endast stöd för heltalssort %d implementerad för bildmängden vid %L"
#: fortran/trans-stmt.c:2723
-#, fuzzy, gcc-internal-format
-#| msgid "gfc_trans_code(): Bad statement code"
+#, gcc-internal-format
msgid "gfc_trans_select(): Bad type for case expr."
-msgstr "gfc_trans_code(): Felaktig satskod"
+msgstr "gfc_trans_select(): Felaktig typ för Bad type for case-uttryck."
#: fortran/trans-types.c:510
-#, fuzzy, gcc-internal-format
-#| msgid "INTEGER(KIND=8) is not available for -fdefault-integer-8 option"
+#, gcc-internal-format
msgid "INTEGER(KIND=8) is not available for %<-fdefault-integer-8%> option"
-msgstr "INTEGER(KIND=8) är inte tillgänglig för flaggan -fdefault-integer-8"
+msgstr "INTEGER(KIND=8) är inte tillgänglig för flaggan %<-fdefault-integer-8%>"
#: fortran/trans-types.c:519
-#, fuzzy, gcc-internal-format
-#| msgid "INTEGER(KIND=8) is not available for -finteger-4-integer-8 option"
+#, gcc-internal-format
msgid "INTEGER(KIND=8) is not available for %<-finteger-4-integer-8%> option"
-msgstr "INTEGER(KIND=8) är inte tillgänglig för flaggan -finteger-4-integer-8"
+msgstr "INTEGER(KIND=8) är inte tillgänglig med flaggan %<-finteger-4-integer-8%>"
#: fortran/trans-types.c:538
-#, fuzzy, gcc-internal-format
-#| msgid "REAL(KIND=8) is not available for -fdefault-real-8 option"
+#, gcc-internal-format
msgid "REAL(KIND=8) is not available for %<-fdefault-real-8%> option"
-msgstr "REAL(KIND=8) är inte tillgänglig för flaggan -fdefault-real-8"
+msgstr "REAL(KIND=8) är inte tillgänglig med flaggan %<-fdefault-real-8%>"
#: fortran/trans-types.c:546
-#, fuzzy, gcc-internal-format
-#| msgid "REAL(KIND=8) is not available for -freal-4-real-8 option"
+#, gcc-internal-format
msgid "REAL(KIND=8) is not available for %<-freal-4-real-8%> option"
-msgstr "REAL(KIND=8) är inte tillgänglig för flaggan -freal-4-real-8"
+msgstr "REAL(KIND=8) är inte tillgänglig med flaggan %<-freal-4-real-8%>"
#: fortran/trans-types.c:554
-#, fuzzy, gcc-internal-format
-#| msgid "REAL(KIND=10) is not available for -freal-4-real-10 option"
+#, gcc-internal-format
msgid "REAL(KIND=10) is not available for %<-freal-4-real-10%> option"
-msgstr "REAL(KIND=10) är inte tillgänglig för flaggan -real-4-real-10"
+msgstr "REAL(KIND=10) är inte tillgänglig med flaggan %<-real-4-real-10%>"
#: fortran/trans-types.c:562
-#, fuzzy, gcc-internal-format
-#| msgid "REAL(KIND=16) is not available for -freal-4-real-16 option"
+#, gcc-internal-format
msgid "REAL(KIND=16) is not available for %<-freal-4-real-16%> option"
-msgstr "REAL(KIND=16) är inte tillgänglig för flaggan -freal-4-real-16"
+msgstr "REAL(KIND=16) är inte tillgänglig med flaggan %<-freal-4-real-16%>"
#: fortran/trans-types.c:577
-#, fuzzy, gcc-internal-format
-#| msgid "Use of -fdefault-double-8 requires -fdefault-real-8"
+#, gcc-internal-format
msgid "Use of %<-fdefault-double-8%> requires %<-fdefault-real-8%>"
-msgstr "Användning av -fdefault-double-8 kräver -fdefault-real-8"
+msgstr "Användning av %<-fdefault-double-8%> kräver %<-fdefault-real-8%>"
#: fortran/trans-types.c:587
-#, fuzzy, gcc-internal-format
-#| msgid "REAL(KIND=4) is not available for -freal-8-real-4 option"
+#, gcc-internal-format
msgid "REAL(KIND=4) is not available for %<-freal-8-real-4%> option"
-msgstr "REAL(KIND=4) är inte tillgänglig för flaggan -freal-8-real-4"
+msgstr "REAL(KIND=4) är inte tillgänglig med flaggan %<-freal-8-real-4%>"
#: fortran/trans-types.c:595
-#, fuzzy, gcc-internal-format
-#| msgid "REAL(KIND=10) is not available for -freal-8-real-10 option"
+#, gcc-internal-format
msgid "REAL(KIND=10) is not available for %<-freal-8-real-10%> option"
-msgstr "REAL(KIND=8) är inte tillgänglig för flaggan -freal-8-real-10"
+msgstr "REAL(KIND=10) är inte tillgänglig med flaggan %<-freal-8-real-10%>"
#: fortran/trans-types.c:603
-#, fuzzy, gcc-internal-format
-#| msgid "REAL(KIND=10) is not available for -freal-8-real-16 option"
+#, gcc-internal-format
msgid "REAL(KIND=10) is not available for %<-freal-8-real-16%> option"
-msgstr "REAL(KIND=10) är inte tillgänglig för flaggan -freal-8-real-16"
+msgstr "REAL(KIND=10) är inte tillgänglig med flaggan %<-freal-8-real-16%>"
#: fortran/trans-types.c:743
#, gcc-internal-format
@@ -53379,22 +53285,19 @@ msgid "bad pc in exception_table"
msgstr "felaktig pc i exception_table"
#: jit/docs/examples/tut05-bf.c:242
-#, fuzzy, gcc-internal-format
-#| msgid "too many arguments"
+#, gcc-internal-format
msgid "too many open parens"
-msgstr "för många argument"
+msgstr "för många öppna parenteser"
#: jit/docs/examples/tut05-bf.c:275
-#, fuzzy, gcc-internal-format
-#| msgid "mismatched arguments"
+#, gcc-internal-format
msgid "mismatching parens"
-msgstr "argumenten stämmer inte överens"
+msgstr "parenteserna stämmer inte överens"
#: jit/docs/examples/tut05-bf.c:310
-#, fuzzy, gcc-internal-format
-#| msgid "failed to open %s"
+#, gcc-internal-format
msgid "unable to open file"
-msgstr "det gick inte att öppna %s"
+msgstr "kan inte att öppna filen"
#: lto/lto-lang.c:812
#, gcc-internal-format
@@ -53428,16 +53331,14 @@ msgid "two or more sections for %s"
msgstr "två eller flera sektioner för %s"
#: lto/lto-symtab.c:196
-#, fuzzy, gcc-internal-format
-#| msgid "%qD is initialized with itself"
+#, gcc-internal-format
msgid "%qD is defined with tls model %s"
-msgstr "%qD initieras med sig själv"
+msgstr "%qD initieras med tls-modell %s"
#: lto/lto-symtab.c:198
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "previously defined here"
+#, gcc-internal-format, gfc-internal-format
msgid "previously defined here as %s"
-msgstr "tidigare definition här"
+msgstr "tidigare definierad här som %s"
#: lto/lto-symtab.c:387
#, gcc-internal-format
@@ -53545,10 +53446,9 @@ msgid "lto_obj_file_open() failed"
msgstr "lto_obj_file_open() misslyckades"
#: lto/lto.c:2520
-#, fuzzy, gcc-internal-format
-#| msgid "atexit failed"
+#, gcc-internal-format
msgid "waitpid failed"
-msgstr "atexit misslyckades"
+msgstr "waitpid misslyckades"
#: lto/lto.c:2523
#, gcc-internal-format
@@ -54520,600 +54420,3 @@ msgstr "%<-fobjc-sjlj-exceptions%> ignoreras för %<-fnext-runtime%> när %<-fob
#, gcc-internal-format
msgid "creating selector for nonexistent method %qE"
msgstr "skapar selektor för icke existerande metod %qE"
-
-#~ msgid "optimizing for size and code size would grow"
-#~ msgstr "optimerar för storlek och kodstorleken skulle växa"
-
-#~ msgid "loop exit may only be reached after undefined behavior"
-#~ msgstr "slingutgången kanske endast nås efter odefinierat beteende"
-
-#~ msgid "possible undefined statement is here"
-#~ msgstr "möjligen odefinierad sats finns här"
-
-#~ msgid "both %<volatile%> and %<constexpr%> cannot be used here"
-#~ msgstr "det går inte att använda både %<volatile%> och %<constexpr%> här"
-
-#~ msgid "unable to find string literal operator %qD"
-#~ msgstr "kan inte hitta en strängliteraloperator %qD"
-
-#~ msgid "%s:%d:%d: Invalid state file; %s"
-#~ msgstr "%s:%d:%d: Felaktig tillståndsfil; %s"
-
-#~ msgid "%s:%d: Invalid state file; %s"
-#~ msgstr "%s:%d: Ogiltig statusfil; %s"
-
-#~ msgid "%s:%d:%d: Invalid state file; "
-#~ msgstr "%s:%d:%d: Ogiltig statusfil: "
-
-#~ msgid "%s:%d: Invalid state file; "
-#~ msgstr "%s:%d: Ogiltig statusfil; "
-
-#~ msgid "Option tag unknown"
-#~ msgstr "Okänd alternativtagg"
-
-#~ msgid "Unexpected type in write_state_scalar_type"
-#~ msgstr "Oväntad typ i write_state_scalar_type"
-
-#~ msgid "Unexpected type in write_state_string_type"
-#~ msgstr "Oväntat typ i write_state_state_type"
-
-#~ msgid "failed to write state trailer [%s]"
-#~ msgstr "det gick inte att skriva avslutning [%s]"
-
-#~ msgid "Failed to open file %s for writing state: %s"
-#~ msgstr "Det gick inte att öppna filen %s för att skriva tillståndet: %s"
-
-#~ msgid "output error when writing state file %s [%s]"
-#~ msgstr "utmatningsfel när tillståndsfilen %s skrevs [%s]"
-
-#~ msgid "failed to close state file %s [%s]"
-#~ msgstr "misslyckades med att stänga tillståndsfilen %s [%s]"
-
-#~ msgid "failed to rename %s to state file %s [%s]"
-#~ msgstr "misslyckades att byta namn på %s till tillståndsfilen %s [%s]"
-
-#~ msgid "Failed to open state file %s for reading [%s]"
-#~ msgstr "Misslyckades att öppna tillståndsfilen %s för läsning [%s]"
-
-#~ msgid "failed to close read state file %s [%s]"
-#~ msgstr "misslyckades med att läst tillståndsfil %s [%s]"
-
-#~ msgid "pex_init failed"
-#~ msgstr "pex_init misslyckades"
-
-#~ msgid "can't get program status"
-#~ msgstr "kan inte ta programstatus"
-
-#~ msgid "%s terminated with signal %d [%s], core dumped"
-#~ msgstr "%s terminerade med signal %d [%s], minnesutskrift skapad"
-
-#~ msgid "%s terminated with signal %d [%s]"
-#~ msgstr "%s terminerade med signal %d [%s]"
-
-#~ msgid "could not write to temporary file %s"
-#~ msgstr "det gick inte att skriva till temporärfil %s"
-
-#~ msgid "fopen: %s"
-#~ msgstr "fopen: %s"
-
-#~ msgid "enabled by default"
-#~ msgstr "aktiverat som standard"
-
-#~ msgid "out of memory"
-#~ msgstr "slut på minne"
-
-#~ msgid "Allow new data races on loads to be introduced"
-#~ msgstr "Tillåt att nya datakapplöpningar vid laddningar introduceras"
-
-#~ msgid "Allow new data races on packed data loads to be introduced"
-#~ msgstr "Tillåt att nya datakapplöpningar vid laddning av packade data introduceras"
-
-#~ msgid "Allow new data races on packed data stores to be introduced"
-#~ msgstr "Tillåt att nya datakapplöpningar vid lagring av packade data introduceras"
-
-#~ msgid "environment variable DJGPP not defined"
-#~ msgstr "omgivningsvariabeln DJGPP är inte definierad"
-
-#~ msgid "environment variable DJGPP points to missing file '%s'"
-#~ msgstr "omgivningsvariabeln DJGPP pekar på fil ”%s” som saknas"
-
-#~ msgid "environment variable DJGPP points to corrupt file '%s'"
-#~ msgstr "omgivningsvariabeln DJGPP pekar på fil ”%s” som är trasig"
-
-#~ msgid "picochip_print_memory_address - Operand isn't memory based"
-#~ msgstr "picochip_print_memory_address - Operand är inte minnesbaserad"
-
-#~ msgid "Unknown mode in print_operand (CONST_DOUBLE) :"
-#~ msgstr "Okänt läge i print_operand (COUNST_DOUBLE) :"
-
-#~ msgid "Bad address, not (reg+disp):"
-#~ msgstr "Felaktig adress, inte (reg+avst):"
-
-#~ msgid "Bad address, not register:"
-#~ msgstr "Felaktig adress, inte register:"
-
-#~ msgid "invalid operand for code: '%c'"
-#~ msgstr "ogiltig operand för kod: ”%c”"
-
-#~ msgid "-fsanitize=thread linking must be done with -pie or -shared"
-#~ msgstr "-fsanitize=thread-länkning måste göra med -pie eller -shared"
-
-#~ msgid "Use big-endian format for unformatted files"
-#~ msgstr "Använd rak byteordning för oformaterade filer"
-
-#~ msgid "Use little-endian format for unformatted files"
-#~ msgstr "Använd omvänd byteordning för oformaterade filer"
-
-#~ msgid "Use native format for unformatted files"
-#~ msgstr "Använd naturlig byteordning för oformaterade filer"
-
-#~ msgid "Swap endianness for unformatted files"
-#~ msgstr "Byt byteordning för oformaterade filer"
-
-#~ msgid "Specify which type of AE to target. This option sets the mul-type and byte-access."
-#~ msgstr "Ange vilken typ av AE att ha som mål. Denna flagga sätter mul-typen och byte-åtkomst."
-
-#~ msgid "Specify which type of multiplication to use. Can be mem, mac or none."
-#~ msgstr "Ange vilken typ av multiplikation att anvnända. Kan vara mem, mac eller none."
-
-#~ msgid "Specify whether the byte access instructions should be used. Enabled by default."
-#~ msgstr "Ange om instruktioner för byteåtkomst skall användas. Aktiverat som standard."
-
-#~ msgid "Enable debug output to be generated."
-#~ msgstr "Aktivera generering av felsökningsutdata."
-
-#~ msgid "Allow a symbol value to be used as an immediate value in an instruction."
-#~ msgstr "Tillåt ett symbolvärde att användas som ett omedelbart värde i en instruktion."
-
-#~ msgid "Generate warnings when inefficient code is known to be generated."
-#~ msgstr "Generera varningar när ineffektiv kod med säkerhet genereras."
-
-#~ msgid "If set, data speculative instructions will be chosen for schedule only if there are no other choices at the moment "
-#~ msgstr "Om satt kommer dataspekulativa instruktioner väljas för schemaläggning endast om det inte finns några andra val för tillfället"
-
-#~ msgid "If set, control speculative instructions will be chosen for schedule only if there are no other choices at the moment "
-#~ msgstr "Om satt kommer styrspekulativa instruktioner väljas för schemaläggning endast om det inte finns några andra val för tillfället"
-
-#~ msgid "Disable bcnz instruction"
-#~ msgstr "Använd inte instruktionen bcnz"
-
-#~ msgid "Enable unaligned load/store instruction"
-#~ msgstr "Använd ojusterade load/store-instruktioner"
-
-#~ msgid "Support SCORE 7 ISA"
-#~ msgstr "Stöd SCORE 7 ISA"
-
-#~ msgid "Support SCORE 7D ISA"
-#~ msgstr "Stöd SCORE 7D ISA"
-
-#~ msgid "Known SCORE architectures (for use with the -march= option):"
-#~ msgstr "Kända SCORE-arkitekturer (att användas med flaggan -march=):"
-
-#~ msgid "Put jumps in call delay slots"
-#~ msgstr "Placera hopp i fördröjda anropsfack"
-
-#~ msgid "Prepend the function label with 12 two-byte Nop instructions, and add a four byte Nop instruction after the label for hotpatching."
-#~ msgstr "Inled funktionsetiketten med 12 tvåbytes Nop-instruktioner, och lägg till en fyrbytes Nop-instruktion efter etiketten för ändring i drift."
-
-#~ msgid "Prepend the function label with the given number of two-byte Nop instructions, and add a four byte Nop instruction after the label for hotpatching."
-#~ msgstr "Inled funktionsetiketten med det angivna antalet tvåbytes Nop-instruktioner, och lägg till en fyrbytes Nop-instruktion enfter etiketten för ändring i drift."
-
-#~ msgid "Assume big endian bytes, little endian words. This option is deprecated."
-#~ msgstr "Antag att byte har rak byteordning, ord har omvänd byteordning. Denna flagga bör undvikas."
-
-#~ msgid "Generate GP base instructions directly."
-#~ msgstr "Generera GP-baserade instruktioner direkt."
-
-#~ msgid "Prevent $fp being allocated during register allocation so that compiler is able to force performing fp-as-gp optimization."
-#~ msgstr "Hindra $fp från att allokeras under registerallokeringen så att kompilatorn kan tvinga fram att fp-som-gp-optimeringar görs."
-
-#~ msgid "Forbid using $fp to access static and global variables. This option strictly forbids fp-as-gp optimization regardless of '-mforce-fp-as-gp'."
-#~ msgstr "Förbjud användning av $fp för att komma åt statiska och globala variabler. Denna flagga förbjuder strikt fp-som-gp-optimieringar oavsett ”-mforce-fp-as-gp”."
-
-#~ msgid "Use special directives to guide linker doing ex9 optimization."
-#~ msgstr "Kör speciella direktiv för att leda länkaren i att göra ex9-optimeringar."
-
-#~ msgid "Perform Semantic function equality"
-#~ msgstr "Utför semantisk funktionslikhet"
-
-#~ msgid "Partition symbols and vars at linktime based on object files they originate from"
-#~ msgstr "Partitionera symboler och variabler vid länktillfället baserat på vilka objektfiler de härrör från"
-
-#~ msgid "Partition functions and vars at linktime into approximately same sized buckets"
-#~ msgstr "Partitionera funktioner och variabler vid länktillfället i hinkar av ungefär samma storlek"
-
-#~ msgid "Put every symbol into separate partition"
-#~ msgstr "Placera varje symbol i en separat partition"
-
-#~ msgid "Disable partioning and streaming"
-#~ msgstr "Avaktivera partitionering och strömning"
-
-#~ msgid "invalid operand for unary %<&%>"
-#~ msgstr "ogiltig operand till unärt %<&%>"
-
-#~ msgid "implicit assignment of %s%s%s hidden field %s%s%s"
-#~ msgstr "implicit tilldelning av dolt fält %4$s%5$s%6$s i %1$s%2$s%3$s"
-
-#~ msgid "invalid memory model for %<__atomic_exchange%>"
-#~ msgstr "ogiltig minnesmodell för %<__atomic_exchange%>"
-
-#~ msgid "invalid entry to Cilk Plus structured block"
-#~ msgstr "ogiltig ingång till Cilk Plus-strukturerat block"
-
-#~ msgid "invalid branch to/from an OpenMP structured block"
-#~ msgstr "ogiltig gren till/från OpenMP-strukturerat block"
-
-#~ msgid "unrecognized command line option \"%s\""
-#~ msgstr "okänd kommandoradsflagga ”%s”"
-
-#~ msgid "only one -flto-partition value can be specified"
-#~ msgstr "bara ett värde för -flto-partition kan anges"
-
-#~ msgid "node not found in symtab decl hashtable"
-#~ msgstr "nod finns inte i hash-tabellen för symboltabelldeklarationer"
-
-#~ msgid "node differs from symtab decl hashtable"
-#~ msgstr "nod skiljer från hash-tabellen för symboltabelldeklarationer"
-
-#~ msgid "non-DECL_ONE_ONLY node in a same_comdat_group list"
-#~ msgstr "icke-DECL_ONE_ONLY-nod i en same_comdat_group-lista"
-
-#~ msgid "-fstrict-volatile-bitfields disabled; it is incompatible with ABI versions < 2"
-#~ msgstr "-fstrict-volatile-bitfields avaktiverat; det är inkomatibelt med ABI-versioner < 2"
-
-#~ msgid "static chain in indirect gimple call"
-#~ msgstr "statisk kedja i indirekt gimple-anrop"
-
-#~ msgid "type mismatch in vector shift expression"
-#~ msgstr "typfel i vektorskiftuttryck"
-
-#~ msgid "non-element sized vector shift of floating point vector"
-#~ msgstr "ej elementstor vektorskiftning eller flyttalsvektor"
-
-#~ msgid "cl_target_option size mismatch in LTO reader and writer"
-#~ msgstr "cl_target_option-storlek stämmer inte överens i LTO-läsare och -skrivare"
-
-#~ msgid "cl_optimization size mismatch in LTO reader and writer"
-#~ msgstr "cl_optimization-storlek stämmer inte överens i LTO-läsare och -skrivare"
-
-#~ msgid "%qD is deprecated (declared at %r%s:%d%R): %s"
-#~ msgstr "%qD bör undvikas (deklarerad vid %r%s:%d%R): %s"
-
-#~ msgid "%qD is deprecated (declared at %r%s:%d%R)"
-#~ msgstr "%qD bör undvikas (deklarerad vid %r%s:%d%R)"
-
-#~ msgid "%qE is deprecated (declared at %r%s:%d%R): %s"
-#~ msgstr "%qE bör undvikas (deklarerad vid %r%s:%d%R): %s"
-
-#~ msgid "%qE is deprecated (declared at %r%s:%d%R)"
-#~ msgstr "%qE bör undvikas (deklarerad vid %r%s:%d%R)"
-
-#~ msgid "type is deprecated (declared at %r%s:%d%R): %s"
-#~ msgstr "typen bör undvikas (deklarerad vid %r%s:%d%R): %s"
-
-#~ msgid "type is deprecated (declared at %r%s:%d%R)"
-#~ msgstr "typen bör undvikas (deklarerad vid %r%s:%d%R)"
-
-#~ msgid "transaction_wrap argument is not a function"
-#~ msgstr "argumentet till transaction_wrap är inte en funktion"
-
-#~ msgid "-Werror=normalized=: set -Wnormalized=nfc"
-#~ msgstr "-Werror=normalized=: sätt -Wnormalized=nfc"
-
-#~ msgid "constant out of range"
-#~ msgstr "konstant utanför intervall"
-
-#~ msgid "%<mwords-little-endian%> is deprecated and will be removed in a future release"
-#~ msgstr "%<mwords-little-endian%> bör undvikas och kommer tas bort i en framtida utgåva"
-
-#~ msgid "ms_abi attribute requires -maccumulate-outgoing-args or subtarget optimization implying it"
-#~ msgstr "attributet ms_abi kräver -maccumulate-outgoing-args eller optimering av undermålarkitektur som implicerar det"
-
-#~ msgid "the last argument must be hint 0 or 1"
-#~ msgstr "det sista argumentet måste vara ett tips 0 eller 1"
-
-#~ msgid "%q+D causes a section type conflict"
-#~ msgstr "%q+D orsakar en sektionstypkonflikt"
-
-#~ msgid "invalid AE type specified (%s)"
-#~ msgstr "ogiltig AE-typ angiven (%s)"
-
-#~ msgid "invalid mul type specified (%s) - expected mac, mul or none"
-#~ msgstr "ogiltig mul-typ angiven (%s) - mac, mul eller none förväntades"
-
-#~ msgid "unexpected mode %s encountered in picochip_emit_save_register"
-#~ msgstr "oväntat läge %s dök upp i picochip_emit_save_register"
-
-#~ msgid "defaulting to stack for %s register creation"
-#~ msgstr "väljer standardläget stack när %s-register skapas"
-
-#~ msgid "LCFI labels have already been deferred"
-#~ msgstr "LCFI-etiketter har redan fördröjts"
-
-#~ msgid "LM label has already been deferred"
-#~ msgstr "LM-etikett har redan fördröjts"
-
-#~ msgid "LCFI labels have already been deferred."
-#~ msgstr "LCFI-etiketter har redan fördröjts."
-
-#~ msgid "picochip_asm_output_opcode - Found multiple lines in VLIW packet %s"
-#~ msgstr "picochip_asm_output_opcode - Hittade multipla rader i VLIW-paket %s"
-
-#~ msgid "picochip_asm_output_opcode - can%'t output unknown operator %c"
-#~ msgstr "picochip_asm_output_opcode - det går inte att mata ut okänd operator %c"
-
-#~ msgid "%s: at least one operand can%'t be handled"
-#~ msgstr "%s: åtminstone en operand kan inte hanteras"
-
-#~ msgid "unknown short branch in %s (type %d)"
-#~ msgstr "okänd kort gren i %s (typ %d)"
-
-#~ msgid "unknown long branch in %s (type %d)"
-#~ msgstr "okänd lång gren i %s (typ %d)"
-
-#~ msgid "PUT uses port array index %d, which is out of range [%d..%d)"
-#~ msgstr "PUT använder portvektorindex %d, som är utanför intervallet [%d..%d)"
-
-#~ msgid "GET uses port array index %d, which is out of range [%d..%d)"
-#~ msgstr "GET använder portvektorindex %d, som är utanför intervallet [%d..%d)"
-
-#~ msgid "too many ALU instructions emitted (%d)"
-#~ msgstr "för många ALU-instruktioner utmatade (%d)"
-
-#~ msgid "%s: Second source operand is not a constant"
-#~ msgstr "%s: Andra källoperanden är inte en konstant"
-
-#~ msgid "%s: Third source operand is not a constant"
-#~ msgstr "%s: Tredje källoperanden är inte en konstant"
-
-#~ msgid "%s: Fourth source operand is not a constant"
-#~ msgstr "%s: Fjärde källoperanden är inte en konstant"
-
-#~ msgid "%s (disable warning using -mno-inefficient-warnings)"
-#~ msgstr "%s (avaktivera varningen med -mno-inefficient-warnings)"
-
-#~ msgid "function %qE with the %qs attribute is not hotpatchable"
-#~ msgstr "funktionen %qE med attributet %qs går inte att ändra i drift"
-
-#~ msgid "invalid vector type for attribute %qs"
-#~ msgstr "ogiltig vektortyp för attributet %qs"
-
-#~ msgid "the size of array %qE can%'t be evaluated"
-#~ msgstr "storleken på vektor %qE kan inte beräknas"
-
-#~ msgid "the size of array can %'t be evaluated"
-#~ msgstr "storleken på vektorn kan inte beräknas"
-
-#~ msgid "variable length array %qE is used"
-#~ msgstr "vektor %qE med variabel längd används"
-
-#~ msgid "array notations cannot be used as a condition for switch statement"
-#~ msgstr "vektornotation kan inte användas som ett villkor i en switch-sats"
-
-#~ msgid "array notations cannot be used as a condition for while statement"
-#~ msgstr "vektornotation kan inte användas som ett vilkor i en while-sats"
-
-#~ msgid "array notations cannot be used as a condition for a do-while statement"
-#~ msgstr "vektornotation kan inte användas som ett villkor i en do-while-sats"
-
-#~ msgid "array notations cannot be used in a condition for a for-loop"
-#~ msgstr "vektornotation kan inte användas som villkor i en for-slinga"
-
-#~ msgid "increment of pointer to unknown structure"
-#~ msgstr "ökning av pekare på okänd post"
-
-#~ msgid "decrement of pointer to unknown structure"
-#~ msgstr "minskning av pekare på okänd post"
-
-#~ msgid "array notation expression cannot be used in a loop%'s condition"
-#~ msgstr "vektornotationsuttryck kan inte användas i en slingas villkor"
-
-#~ msgid "initializing argument %P of %qD"
-#~ msgstr "initierar argument %P till %qD"
-
-#~ msgid "initializing argument %P of %q+D"
-#~ msgstr "initierar argument %P till %q+D"
-
-#~ msgid "scoped enum %qT will not promote to an integral type in a future version of GCC"
-#~ msgstr "enum %qT med räckvidd kommer inte befordras till en heltalstyp i en framtida version av GCC"
-
-#~ msgid "offset of empty base %qT may not be ABI-compliant and maychange in a future version of GCC"
-#~ msgstr "förskjutning av tom bas %qT följer kanske inte ABI:et och kan ändras i en framtida version av GCC"
-
-#~ msgid "class %qT will be considered nearly empty in a future version of GCC"
-#~ msgstr "klass %qT kommer betraktas som nästan tom i en framtida version av GCC"
-
-#~ msgid "offset of virtual base %qT is not ABI-compliant and may change in a future version of GCC"
-#~ msgstr "förskjutning av virtuell bas %qT följer inte ABI:et och kan ändras i en framtida version av GCC"
-
-#~ msgid "size assigned to %qT may not be ABI-compliant and may change in a future version of GCC"
-#~ msgstr "storlek tilldelad till %qT följer kanske inte ABI:et och kan ändras i en framtida version av GCC"
-
-#~ msgid "the offset of %qD may not be ABI-compliant and may change in a future version of GCC"
-#~ msgstr "förskjutningen för %qD följer kanske inte ABI:et och kan ändras i en framtida version av GCC"
-
-#~ msgid "%q+D contains empty classes which may cause base classes to be placed at different locations in a future version of GCC"
-#~ msgstr "%q+D innehåller tomma klasser som kan få grundklasser att läggas på annan plats i en framtida version av GCC"
-
-#~ msgid "layout of classes derived from empty class %qT may change in a future version of GCC"
-#~ msgstr "utplaceringen av klasser härledda från en tom klass %qT kan ändras i en framtida version av GCC"
-
-#~ msgid "%qD cannot be scalar when %qD is not"
-#~ msgstr "%qD kan inte vara en skalär när %qD inte är det"
-
-#~ msgid "%q+D: visibility attribute ignored because it"
-#~ msgstr "%q+D: synlighetsattribut ignorerat för att det"
-
-#~ msgid "conflicts with previous declaration here"
-#~ msgstr "står i konflikt med tidigare deklaration här"
-
-#~ msgid "%q#D is not a static member of %q#T"
-#~ msgstr "%q#D är inte en statisk medlem av %q#T"
-
-#~ msgid "declaration of %qD as array of %<auto%>"
-#~ msgstr "deklaration av %qD som en vektor av %<auto%>"
-
-#~ msgid "array of array of runtime bound"
-#~ msgstr "vektor av vektor av körtidsgräns"
-
-#~ msgid "can%'t initialize friend function %qs"
-#~ msgstr "det går inte att initiera vänfunktionen %qs"
-
-#~ msgid "reference to array of runtime bound"
-#~ msgstr "referens till vektor av körtidsgräns"
-
-#~ msgid "pointer to array of runtime bound"
-#~ msgstr "pekare till vektor av körtidsgräns"
-
-#~ msgid "typedef naming array of runtime bound"
-#~ msgstr "typedef som namnger vektor av körtidsgräns"
-
-#~ msgid "uninitialized member %qD with %<const%> type %qT"
-#~ msgstr "oinitierad medlem %qD med %<const%>-typ %qT"
-
-#~ msgid "uninitialized reference member %qD"
-#~ msgstr "oinitierad referensmedlem %qD"
-
-#~ msgid "ISO C++ does not support variable-length array types"
-#~ msgstr "ISO C++ stödjer inte vektortyper med variabel längd"
-
-#~ msgid "uninitialized non-static const member %q#D"
-#~ msgstr "oinitierad ej statisk const-medlem %q#D"
-
-#~ msgid "uninitialized non-static reference member %q#D"
-#~ msgstr "oinitierad ej statisk referensmedlem %q#D"
-
-#~ msgid "vtable layout for class %qT may not be ABI-compliantand may change in a future version of GCC due to implicit virtual destructor"
-#~ msgstr "vtable-utplacering för klass %qT följer kanske inte ABI:et och kan ändras i en framtida version av GCC på grund av implicit virtuell destruerare"
-
-#~ msgid "declaration of %qD shadows a member of 'this'"
-#~ msgstr "deklaration av %qD skuggar en medlem av ”this”"
-
-#~ msgid "range-based %<for%> loops are not allowed in C++98 mode"
-#~ msgstr "intervallbaserade %<for%>-slingor är inte tillåtna i C++98-läge"
-
-#~ msgid "invalid type in declaration"
-#~ msgstr "ogiltig typ i deklaration"
-
-#~ msgid "parameter pack %qT must be at the end of the template parameter list"
-#~ msgstr "parameterpaket %qT måste vara vid slutet av mallens parameterlista"
-
-#~ msgid "wrong number of template arguments (%d, should be %d or more)"
-#~ msgstr "fel antal mallargument (%d, skulle vara %d eller fler)"
-
-#~ msgid "template instantiation depth exceeds maximum of %d (use -ftemplate-depth= to increase the maximum) instantiating %qD"
-#~ msgstr "mallinstansieringsdjupet överskrider maxvärdet på %d (använd -ftemplate-depth= för att öka maxvärdet) vid instansiering av %qD"
-
-#~ msgid "cannot declare reference to array of runtime bound"
-#~ msgstr "det går inte att deklarera en referens till en vektor av körtidsgräns"
-
-#~ msgid "cannot declare pointer to array of runtime bound"
-#~ msgstr "det går inte att deklarera en pekare till en vektor av körtidsgräns"
-
-#~ msgid "%s %+#T"
-#~ msgstr "%s %+#T"
-
-#~ msgid "typeid of array of runtime bound"
-#~ msgstr "type-id till vektor av av körtidsgräns"
-
-#~ msgid "invalid use of non-static data member %q+D"
-#~ msgstr "ogiltig användning av icke-statisk datamedlem %q+D"
-
-#~ msgid "from this location"
-#~ msgstr "härifrån"
-
-#~ msgid "use of parameter %qD outside function body"
-#~ msgstr "användning av parametern %qD utanför funktionskropp"
-
-#~ msgid "taking decltype of array of runtime bound"
-#~ msgstr "tar decltype på en vektor med körtidsbegränsning"
-
-#~ msgid "__is_convertible_to"
-#~ msgstr "__is_convertible_to"
-
-#~ msgid "use of the value of the object being constructed in a constant expression"
-#~ msgstr "användning av värdet på objektet som konstrueras i ett konstant uttryck"
-
-#~ msgid "calling a member function of the object being constructed in a constant expression"
-#~ msgstr "anrop av en medlemsfunktion i objektet som konstrueras i ett konstant uttryck"
-
-#~ msgid "taking sizeof array of runtime bound"
-#~ msgstr "tar sizeof på vektor av körtidsgräns"
-
-#~ msgid "invalid access to non-static data member %qD of NULL object"
-#~ msgstr "ogiltig åtkomst av ickestatisk datamedlem %qD från NULL-objekt"
-
-#~ msgid "(perhaps the %<offsetof%> macro was used incorrectly)"
-#~ msgstr "(kanske makrot %<offsetof%> användes felaktigt)"
-
-#~ msgid "%qD has no member named %qE"
-#~ msgstr "%qD har ingen medlem med namnet %qE"
-
-#~ msgid "taking address of array of runtime bound"
-#~ msgstr "tar adressen till vektor av körtidsgräns"
-
-#~ msgid "cannot initialize arrays using this syntax"
-#~ msgstr "det går inte att initiera vektorer med denna syntax"
-
-#~ msgid "uninitialized const member %qD"
-#~ msgstr "oinitierad const-medlem %qD"
-
-#~ msgid "member %qD with uninitialized const fields"
-#~ msgstr "medlem %qD med oinitierade const-fält"
-
-#~ msgid "'dim' argument of '%s' intrinsic at %L is not a valid dimension index"
-#~ msgstr "”dim”-argumentet till inbyggd ”%s” vid %L är inte ett giltigt dimensionsindex"
-
-#~ msgid "ATOM and VALUE argument of the %s intrinsic function shall have the same type at %L"
-#~ msgstr "ATOM- och VALUE-argumenten till den inbyggda funktionen %s måste ha samma typ vid %L"
-
-#~ msgid "'%s' argument of '%s' intrinsic at %L must be a non-derived type"
-#~ msgstr "”%s”-argumentet till inbyggd ”%s” vid %L måste vara en icke härledd typ"
-
-#~ msgid "TODO: Deferred character length variable at %C cannot yet be associated with unlimited polymorphic entities"
-#~ msgstr "ATT GÖRA: Fördröjd teckenlängdsvariabel vid %C kan inte ännu associeras med obegränsat polymorfa enheter"
-
-#~ msgid "Missing closing quote '\"' for binding label at %C"
-#~ msgstr "Avslutande citationstecken '”' saknas för att binda etikett vid %C"
-
-#~ msgid "Missing closing quote ''' for binding label at %C"
-#~ msgstr "Avslutande citationstecken ”'” saknas för att binda etikett vid %C"
-
-#~ msgid "Expected ',' at %C"
-#~ msgstr "”,” förväntades vid %C"
-
-#~ msgid "Internal Error at (1):"
-#~ msgstr "Internt fel vid (1):"
-
-#~ msgid "Embedded space in NAME= specifier at %C"
-#~ msgstr "Inbäddad blank i NAME=-specificerare vid %C"
-
-#~ msgid "Expected ')' or ',' at %C"
-#~ msgstr "”)” eller ”,” förväntades vid %C"
-
-#~ msgid "%s is not INTRINSIC procedure name at %C"
-#~ msgstr "%s är inte namn på en INTRINSIC procedur vid %C"
-
-#~ msgid "COPYIN clause object '%s' at %L has ALLOCATABLE components"
-#~ msgstr "COPYIN-klausulobjekt ”%s” vid %L har ALLOCATABLE-komponenter"
-
-#~ msgid "COPYPRIVATE clause object '%s' at %L has ALLOCATABLE components"
-#~ msgstr "COPYPRIVATE-klausulobjekt ”%s” vid %L har ALLOCATABLE-komponenter"
-
-#~ msgid "%s clause object '%s' has ALLOCATABLE components at %L"
-#~ msgstr "%s-klausulobjekt ”%s” har ALLOCATABLE-komponenter vid %L"
-
-#~ msgid "%c REDUCTION variable '%s' at %L must be of numeric type, got %s"
-#~ msgstr "%c REDUCTION-variabel ”%s” vid %L måste vara av numerisk typ, fick %s"
-
-#~ msgid "%s REDUCTION variable '%s' must be LOGICAL at %L"
-#~ msgstr "%s REDUCTION-variabel ”%s” måste vara LOGICAL vid %L"
-
-#~ msgid "%s REDUCTION variable '%s' must be INTEGER or REAL at %L"
-#~ msgstr "%s REDUCTION-variabel ”%s” måste vara INTEGER eller REAL vid %L"
-
-#~ msgid "Argument to -fcoarray is not valid: %s"
-#~ msgstr "Argumentet till -fcoarray är inte giltigt: %s"
-
-#~ msgid "Function reference to '%s' at %L is to a non-PURE procedure within a PURE procedure"
-#~ msgstr "Funktionsreferens till ”%s” vid %L är till en icke-PURE-procedur inuti en PURE-procedur"
diff --git a/gcc/reorg.c b/gcc/reorg.c
index b24a3f04388..6de8a544df5 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -473,7 +473,7 @@ find_end_label (rtx kind)
}
else
{
- if (HAVE_epilogue && ! targetm.have_return ())
+ if (targetm.have_epilogue () && ! targetm.have_return ())
/* The RETURN insn has its delay slot filled so we cannot
emit the label just before it. Since we already have
an epilogue and cannot emit a new RETURN, we cannot
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 7c40e124334..426e3056d08 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -172,7 +172,7 @@ void
emit_jump (rtx label)
{
do_pending_stack_adjust ();
- emit_jump_insn (gen_jump (label));
+ emit_jump_insn (targetm.gen_jump (label));
emit_barrier ();
}
diff --git a/gcc/target-insns.def b/gcc/target-insns.def
index bf5b36742b5..0d8f5014928 100644
--- a/gcc/target-insns.def
+++ b/gcc/target-insns.def
@@ -30,5 +30,15 @@
Patterns that take no operands should have a prototype "(void)".
Instructions should be documented in md.texi rather than here. */
+DEF_TARGET_INSN (canonicalize_funcptr_for_compare, (rtx x0, rtx x1))
+DEF_TARGET_INSN (epilogue, (void))
+DEF_TARGET_INSN (jump, (rtx x0))
+DEF_TARGET_INSN (load_multiple, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (mem_signal_fence, (rtx x0))
+DEF_TARGET_INSN (mem_thread_fence, (rtx x0))
+DEF_TARGET_INSN (memory_barrier, (void))
+DEF_TARGET_INSN (prologue, (void))
DEF_TARGET_INSN (return, (void))
+DEF_TARGET_INSN (sibcall_epilogue, (void))
DEF_TARGET_INSN (simple_return, (void))
+DEF_TARGET_INSN (store_multiple, (rtx x0, rtx x1, rtx x2))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b4bd5dae784..aca88862aa9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,136 @@
+2015-07-01 Patrick Palka <ppalka@gcc.gnu.org>
+
+ PR c++/66686
+ * g++.dg/template/pr66686.C: New test.
+
+2015-06-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/lto17.ad[sb]: New test.
+
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ * jit.dg/all-non-failing-tests.h: Add test-switch.c.
+ * jit.dg/test-error-gcc_jit_block_end_with_switch-NULL-case.c: New
+ testcase.
+ * jit.dg/test-error-gcc_jit_block_end_with_switch-mismatching-case-type.c:
+ New testcase.
+ * jit.dg/test-error-gcc_jit_block_end_with_switch-overlapping-ranges.c:
+ New testcase.
+ * jit.dg/test-error-gcc_jit_context_new_case-non-const-label.c:
+ New testcase.
+ * jit.dg/test-error-gcc_jit_context_new_case-non-integer-type.c:
+ New testcase.
+ * jit.dg/test-error-gcc_jit_context_new_case-reversed-endpoints.c:
+ New testcase.
+ * jit.dg/test-switch.c: New testcase.
+ * jit.dg/test-switch.cc: New testcase.
+
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/66546
+ * jit.dg/all-non-failing-tests.h: Add note about
+ test-validly-unreachable-block.c.
+ * jit.dg/test-validly-unreachable-block.c: New file.
+
+2015-06-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/66628
+ * jit.dg/all-non-failing-tests.h: Add note about
+ test-extra-options.c.
+ * jit.dg/test-extra-options.c: New testcase.
+
+2015-06-30 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR debug/66691
+ * gcc.target/i386/pr66691.c: New.
+
+2015-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/iamcu/abi-iamcu.exp: New file.
+ * gcc.target/i386/iamcu/args.h: Likewise.
+ * gcc.target/i386/iamcu/asm-support.S: Likewise.
+ * gcc.target/i386/iamcu/defines.h: Likewise.
+ * gcc.target/i386/iamcu/macros.h: Likewise.
+ * gcc.target/i386/iamcu/test_3_element_struct_and_unions.c: Likewise.
+ * gcc.target/i386/iamcu/test_basic_64bit_returning.c: Likewise.
+ * gcc.target/i386/iamcu/test_basic_alignment.c: Likewise.
+ * gcc.target/i386/iamcu/test_basic_array_size_and_align.c: Likewise.
+ * gcc.target/i386/iamcu/test_basic_returning.c: Likewise.
+ * gcc.target/i386/iamcu/test_basic_sizes.c: Likewise.
+ * gcc.target/i386/iamcu/test_basic_struct_size_and_align.c: Likewise.
+ * gcc.target/i386/iamcu/test_basic_union_size_and_align.c: Likewise.
+ * gcc.target/i386/iamcu/test_bitfields.c: Likewise.
+ * gcc.target/i386/iamcu/test_complex_returning.c: Likewise.
+ * gcc.target/i386/iamcu/test_passing_floats.c: Likewise.
+ * gcc.target/i386/iamcu/test_passing_integers.c: Likewise.
+ * gcc.target/i386/iamcu/test_passing_structs.c: Likewise.
+ * gcc.target/i386/iamcu/test_passing_structs_and_unions.c: Likewise.
+ * gcc.target/i386/iamcu/test_passing_unions.c: Likewise.
+ * gcc.target/i386/iamcu/test_struct_returning.c: Likewise.
+ * gcc.target/i386/iamcu/test_varargs.c: Likewise.
+
+2015-06-30 Marek Polacek <polacek@redhat.com>
+
+ * gcc.dg/fold-minus-6.c: New test.
+
+ * gcc.dg/fold-ior-3.c: New test.
+
+2015-06-30 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement N4197 - Adding u8 character literals
+ * g++.dg/cpp1z/utf8.C: New.
+ * g++.dg/cpp1z/utf8-neg.C: New.
+ * g++.dg/cpp1z/udlit-utf8char.C: New.
+
+2015-06-30 Marek Polacek <polacek@redhat.com>
+
+ * gcc.dg/fold-ior-2.c (fn4): Swap operands.
+
+2015-06-30 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.dg/parloops-exit-first-loop-alt-5.c: New test.
+ * gcc.dg/parloops-exit-first-loop-alt-6.c: New test.
+ * gcc.dg/parloops-exit-first-loop-alt-7.c: New test.
+ * gcc.dg/parloops-exit-first-loop-alt.c: Update comment.
+
+2015-06-30 Marek Polacek <polacek@redhat.com>
+
+ * gcc.dg/fold-ior-2.c: New test.
+
+2015-06-30 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/66652
+ * gcc.dg/parloops-exit-first-loop-alt-pr66652.c: New test.
+ * gcc.dg/parloops-exit-first-loop-alt-3.c (f): Rewrite using restrict
+ pointers.
+ * gcc.dg/parloops-exit-first-loop-alt.c: Same.
+
+2015-06-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/65977
+ * g++.dg/cpp0x/constexpr-friend-3.C: New.
+ * g++.dg/cpp0x/constexpr-friend-2.C: Adjust.
+
+2015-06-29 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR fortran/66605
+ * gfortran.dg/wunused-parameter.f90: New test.
+
+2015-06-29 Richard Henderson <rth@redhat.com>
+
+ * gcc.target/i386/asm-flag-1.c: New.
+ * gcc.target/i386/asm-flag-2.c: New.
+ * gcc.target/i386/asm-flag-3.c: New.
+ * gcc.target/i386/asm-flag-4.c: New.
+ * gcc.target/i386/asm-flag-5.c: New.
+
+2015-06-29 Marek Polacek <polacek@redhat.com>
+
+ PR c/66322
+ * c-c++-common/pr60439.c: Add dg-prune-output and add switch cases.
+ * c-c++-common/pr66322.c: New test.
+ * g++.dg/eh/scope1.C: Remove dg-warning.
+
2015-06-29 Richard Biener <rguenther@suse.de>
PR tree-optimization/66677
diff --git a/gcc/testsuite/c-c++-common/pr60439.c b/gcc/testsuite/c-c++-common/pr60439.c
index 3368a0b944d..68bd33c22cb 100644
--- a/gcc/testsuite/c-c++-common/pr60439.c
+++ b/gcc/testsuite/c-c++-common/pr60439.c
@@ -1,5 +1,6 @@
/* PR c/60439 */
/* { dg-do compile } */
+/* { dg-prune-output "case label value exceeds" } */
#ifndef __cplusplus
# define bool _Bool
@@ -11,18 +12,30 @@ void
f1 (bool b)
{
switch (b) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
}
void
f2 (int a, int b)
{
switch (a && b) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch ((bool) (a && b)) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch ((a && b) || a) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
/* No warnings on following. */
switch ((int) (a && b))
break;
@@ -38,35 +51,65 @@ void
f3 (int a)
{
switch (!!a) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (!a) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
}
void
f4 (void)
{
switch (foo ()) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
}
void
f5 (int a)
{
switch (a == 3) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (a != 3) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (a > 3) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (a < 3) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (a <= 3) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (a >= 3) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (foo (), foo (), a >= 42) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (a == 3, a & 4, a ^ 5, a)
break;
switch ((int) (a == 3))
@@ -79,11 +122,20 @@ void
f6 (bool b)
{
switch (b) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (!b) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
switch (b++) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
}
void
@@ -91,7 +143,10 @@ f7 (void)
{
bool b;
switch (b = 1) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 3:
+ break;
+ }
}
void
@@ -104,5 +159,8 @@ f8 (int i)
switch ((unsigned int) i)
break;
switch ((bool) i) /* { dg-warning "switch condition has" } */
- break;
+ {
+ case 11:
+ break;
+ }
}
diff --git a/gcc/testsuite/c-c++-common/pr66322.c b/gcc/testsuite/c-c++-common/pr66322.c
new file mode 100644
index 00000000000..eb1e9e4a2ed
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr66322.c
@@ -0,0 +1,144 @@
+/* PR c/66322 */
+/* { dg-do compile } */
+
+#ifndef __cplusplus
+# define bool _Bool
+# define true 1
+# define false 0
+#endif
+
+void
+nowarn (bool b)
+{
+ switch (b)
+ ;
+
+ switch (b)
+ {
+ case true:
+ case false:
+ break;
+ }
+
+ switch (b)
+ {
+ case true:
+ break;
+ }
+
+ switch (b)
+ {
+ case true:
+ default:
+ break;
+ }
+
+ switch (b)
+ {
+ case false:
+ break;
+ }
+
+ switch (b)
+ {
+ case false:
+ default:
+ break;
+ }
+
+ switch (b)
+ {
+ default:
+ break;
+ }
+
+ switch (b)
+ {
+ case false ... true:
+ break;
+ }
+
+ switch (b)
+ {
+ case 1:
+ switch (b)
+ {
+ case true:
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void
+warn (bool b)
+{
+ switch (b) /* { dg-warning "switch condition has" } */
+ {
+ case true:
+ case false:
+ default:
+ break;
+ }
+
+ switch (b) /* { dg-warning "switch condition has" } */
+ {
+ case false ... true:
+ default:
+ break;
+ }
+}
+
+void
+warn2 (int n)
+{
+ switch (n == 2) /* { dg-warning "switch condition has" } */
+ {
+ case 0 ... 2: /* { dg-warning "upper value" "" { target c++ } } */
+ default:
+ break;
+ }
+
+ switch (n == 2) /* { dg-warning "switch condition has" } */
+ {
+ case 1 ... 10: /* { dg-warning "upper value" "" { target c++ } } */
+ default:
+ break;
+ }
+
+ switch (n == 2) /* { dg-warning "switch condition has" } */
+ {
+ case 2: /* { dg-warning "case label" "" { target c++ } } */
+ break;
+ }
+
+ switch (n == 2) /* { dg-warning "switch condition has" } */
+ {
+ case 0:
+ case 1:
+ case -1: /* { dg-warning "case label" "" { target c++ } } */
+ break;
+ }
+
+ switch (n == 2) /* { dg-warning "switch condition has" } */
+ {
+ case -1 ... 1: /* { dg-warning "lower value" "" { target c++ } } */
+ break;
+ }
+
+ switch (n == 2) /* { dg-warning "switch condition has" } */
+ {
+ case -1 ... 0: /* { dg-warning "lower value" "" { target c++ } } */
+ default:
+ break;
+ }
+
+ switch (n == 2) /* { dg-warning "switch condition has" } */
+ {
+ case -10 ... -1: /* { dg-warning "case label" "" { target c++ } } */
+ default:
+ break;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend-2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend-2.C
index 36799b43587..b2ddc218d4a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend-2.C
@@ -3,5 +3,5 @@
template<typename T> void f(T);
template <class T> class A {
- friend constexpr void f<>(int); // { dg-error "'constexpr' is not allowed" }
+ friend constexpr void f<>(int);
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend-3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend-3.C
new file mode 100644
index 00000000000..aec38eb68ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend-3.C
@@ -0,0 +1,21 @@
+// PR c++/65977
+// { dg-do compile { target c++11 } }
+
+template<__SIZE_TYPE__>
+class bitset;
+
+template<__SIZE_TYPE__ N>
+constexpr bool operator==(const bitset<N>&, const bitset<N>&) noexcept;
+
+template<__SIZE_TYPE__ N>
+class bitset
+{
+ friend constexpr bool operator== <>(const bitset<N>&,
+ const bitset<N>&) noexcept;
+};
+
+template<__SIZE_TYPE__ N>
+constexpr bool operator==(const bitset<N>&, const bitset<N>&) noexcept
+{
+ return true;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/udlit-utf8char.C b/gcc/testsuite/g++.dg/cpp1z/udlit-utf8char.C
new file mode 100644
index 00000000000..fb9cdf18fd2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/udlit-utf8char.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+// { dg-options "-std=c++1z" }
+
+constexpr int
+operator""_foo(char c)
+{ return c * 100; }
+
+auto cc = u8'8'_foo;
diff --git a/gcc/testsuite/g++.dg/cpp1z/utf8-neg.C b/gcc/testsuite/g++.dg/cpp1z/utf8-neg.C
new file mode 100644
index 00000000000..339f0e3c029
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/utf8-neg.C
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c++1z" } */
+
+const static char c0 = u8''; // { dg-error "empty character" }
+const static char c1 = u8'ab'; // { dg-warning "multi-character character constant" }
+const static char c2 = u8'\u0124'; // { dg-warning "multi-character character constant" }
+const static char c3 = u8'\U00064321'; // { dg-warning "multi-character character constant" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/utf8.C b/gcc/testsuite/g++.dg/cpp1z/utf8.C
new file mode 100644
index 00000000000..52816f85918
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/utf8.C
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-std=c++1z" }
+
+#include <cassert>
+#include <experimental/type_traits>
+
+auto c = 'c';
+auto u8c = u8'c';
+
+static_assert(std::experimental::is_same_v<decltype(u8c), decltype(c)>, "");
+
+auto u8s = u8"c";
+auto x = u8s[0];
+
+static_assert(std::experimental::is_same_v<decltype(u8c), decltype(x)>, "");
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/tls1.C b/gcc/testsuite/g++.dg/debug/dwarf2/tls1.C
new file mode 100644
index 00000000000..6286d7b27ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/tls1.C
@@ -0,0 +1,7 @@
+// PR c++/66653
+// { dg-options "-gdwarf" }
+
+template <typename T> class A
+{
+ static __thread T a;
+};
diff --git a/gcc/testsuite/g++.dg/eh/scope1.C b/gcc/testsuite/g++.dg/eh/scope1.C
index 8d553d8295b..276e0d6e588 100644
--- a/gcc/testsuite/g++.dg/eh/scope1.C
+++ b/gcc/testsuite/g++.dg/eh/scope1.C
@@ -31,7 +31,7 @@ void f3 ()
void f4 ()
{
- switch (C br = C()) /* { dg-warning "switch condition has" } */
+ switch (C br = C())
{
default:
abort ();
diff --git a/gcc/testsuite/g++.dg/template/pr66686.C b/gcc/testsuite/g++.dg/template/pr66686.C
new file mode 100644
index 00000000000..d8aea625d46
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr66686.C
@@ -0,0 +1,15 @@
+// PR c++/66686
+
+template <int>
+struct Y { };
+
+template <class B, template <template <B> class Z> class C>
+struct X
+{
+ C<Y> a; // { dg-bogus "mismatch" }
+};
+
+template <template <int> class>
+struct A { };
+
+X<int, A> a;
diff --git a/gcc/testsuite/g++.dg/tls/tls_model1.C b/gcc/testsuite/g++.dg/tls/tls_model1.C
new file mode 100644
index 00000000000..a1520a1ba2f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tls/tls_model1.C
@@ -0,0 +1,8 @@
+// { dg-require-effective-target tls }
+// { dg-options "-g" }
+
+template <class T>
+void f()
+{
+ static __thread int i __attribute ((tls_model ("local-exec")));
+}
diff --git a/gcc/testsuite/gcc.dg/fold-ior-2.c b/gcc/testsuite/gcc.dg/fold-ior-2.c
new file mode 100644
index 00000000000..41b372d06fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-ior-2.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int
+fn1 (int x)
+{
+ return ~x | x;
+}
+
+int
+fn2 (int x)
+{
+ return x | ~x;
+}
+
+unsigned int
+fn3 (unsigned int x)
+{
+ return ~x | x;
+}
+
+unsigned int
+fn4 (unsigned int x)
+{
+ return x | ~x;
+}
+
+int
+fn5 (int x)
+{
+ return ~x | (unsigned) x;
+}
+
+int
+fn6 (int x)
+{
+ return (unsigned) ~x | x;
+}
+
+int
+fn7 (int x)
+{
+ return ~(unsigned) x | x;
+}
+
+/* { dg-final { scan-tree-dump-not "~" "cddce1" } } */
+/* { dg-final { scan-tree-dump-not " \\| " "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-ior-3.c b/gcc/testsuite/gcc.dg/fold-ior-3.c
new file mode 100644
index 00000000000..ed89ff9188c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-ior-3.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int
+fn1 (_Bool a)
+{
+ return ((int) a) | ((int) ~a);
+}
+
+int
+fn2 (unsigned char a)
+{
+ return ((int) a) | ((int) ~a);
+}
+
+int
+fn3 (unsigned short a)
+{
+ return ((int) a) | ((int) ~a);
+}
+
+int
+fn4 (signed char a)
+{
+ return ((int) a) | ((int) ~a);
+}
+
+int
+fn5 (signed short a)
+{
+ return ((int) a) | ((int) ~a);
+}
+
+/* { dg-final { scan-tree-dump-not "~" "cddce1" } } */
+/* { dg-final { scan-tree-dump-not " \\| " "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-minus-6.c b/gcc/testsuite/gcc.dg/fold-minus-6.c
new file mode 100644
index 00000000000..1c22c252f72
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-minus-6.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int
+fn1 (int x)
+{
+ return 42L - (42 / x) * x;
+}
+
+long
+fn2 (int x)
+{
+ return 42L - (42 / x) * x;
+}
+
+int
+fn3 (long int x)
+{
+ return 42L - (42 / x) * x;
+}
+
+int
+fn4 (int a, int b)
+{
+ return a - (unsigned) ((a / b) * b);
+}
+
+int
+fn5 (int a, unsigned int b)
+{
+ return a - ((a / b) * b);
+}
+
+unsigned int
+fn6 (int a, int b)
+{
+ return a - ((a / b) * b);
+}
+
+/* { dg-final { scan-tree-dump-not " / " "cddce1" } } */
+/* { dg-final { scan-tree-dump-not " - " "cddce1" } } */
+/* { dg-final { scan-tree-dump-not " \\+ " "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-3.c b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-3.c
index b0fde372a14..fec53a19628 100644
--- a/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-3.c
+++ b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-3.c
@@ -7,7 +7,7 @@
unsigned int *a;
unsigned int
-f (unsigned int n)
+f (unsigned int n, unsigned int *__restrict__ a)
{
int i;
unsigned int sum = 1;
diff --git a/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-5.c b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-5.c
new file mode 100644
index 00000000000..3f799cf234d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-5.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target pthread } */
+/* { dg-options "-O2 -ftree-parallelize-loops=2 -fdump-tree-parloops" } */
+
+/* Variable bound, vector addition, unsigned loop counter, unsigned bound. */
+
+void
+f (unsigned int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
+ unsigned int *__restrict__ c)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; ++i)
+ c[i] = a[i] + b[i];
+}
+
+/* Three times a store:
+ - one in f._loopfn.0
+ - one in the parallel
+ - one in the low iteration count loop
+ Crucially, none for a peeled off last iteration following the parallel. */
+/* { dg-final { scan-tree-dump-times "(?n)^ \\*_\[0-9\]*" 3 "parloops" } } */
diff --git a/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-6.c b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-6.c
new file mode 100644
index 00000000000..ee19a55849a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-6.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target pthread } */
+/* { dg-options "-O2 -ftree-parallelize-loops=2 -fdump-tree-parloops" } */
+
+/* Variable bound, vector addition, unsigned loop counter, signed bound. */
+
+void
+f (int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
+ unsigned int *__restrict__ c)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; ++i)
+ c[i] = a[i] + b[i];
+}
+
+/* Three times a store:
+ - one in f._loopfn.0
+ - one in the parallel
+ - one in the low iteration count loop
+ Crucially, none for a peeled off last iteration following the parallel. */
+/* { dg-final { scan-tree-dump-times "(?n)^ \\*_\[0-9\]*" 3 "parloops" } } */
diff --git a/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-7.c b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-7.c
new file mode 100644
index 00000000000..c3373425281
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-7.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target pthread } */
+/* { dg-options "-O2 -ftree-parallelize-loops=2 -fdump-tree-parloops" } */
+
+/* Variable bound, vector addition, signed loop counter, signed bound. */
+
+void
+f (int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
+ unsigned int *__restrict__ c)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ c[i] = a[i] + b[i];
+}
+
+/* Three times a store:
+ - one in f._loopfn.0
+ - one in the parallel
+ - one in the low iteration count loop
+ Crucially, none for a peeled off last iteration following the parallel. */
+/* { dg-final { scan-tree-dump-times "(?n)^ \\*_\[0-9\]*" 3 "parloops" } } */
diff --git a/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-pr66652.c b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-pr66652.c
new file mode 100644
index 00000000000..2ea097d06f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt-pr66652.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target pthread } */
+/* { dg-options "-O2 -ftree-parallelize-loops=2 -fdump-tree-parloops" } */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+unsigned int
+f (unsigned int n, unsigned int sum)
+{
+ unsigned int i;
+
+ i = UINT_MAX;
+ do
+ {
+ sum += i % 13;
+ i++;
+ }
+ while (i < n - 1);
+
+ return sum;
+}
+
+/* Four times % 13:
+ - once in f._loopfn.0
+ - once in the parallel
+ - once in the low iteration count loop
+ - once for a peeled off last iteration following the parallel.
+ In other words, we want try_transform_to_exit_first_loop_alt to fail. */
+/* { dg-final { scan-tree-dump-times "(?n)% 13" 4 "parloops" } } */
diff --git a/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt.c b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt.c
index b36f01b8f8f..0b6916507f4 100644
--- a/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt.c
+++ b/gcc/testsuite/gcc.dg/parloops-exit-first-loop-alt.c
@@ -2,16 +2,11 @@
/* { dg-require-effective-target pthread } */
/* { dg-options "-O2 -ftree-parallelize-loops=2 -fdump-tree-parloops" } */
-/* Variable bound, vector addition. */
-
-#define N 1000
-
-unsigned int a[N];
-unsigned int b[N];
-unsigned int c[N];
+/* Variable bound, vector addition, signed loop counter, unsigned bound. */
void
-f (unsigned int n)
+f (unsigned int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
+ unsigned int *__restrict__ c)
{
int i;
@@ -19,9 +14,9 @@ f (unsigned int n)
c[i] = a[i] + b[i];
}
-/* Three times three array accesses:
- - three in f._loopfn.0
- - three in the parallel
- - three in the low iteration count loop
+/* Three times a store:
+ - one in f._loopfn.0
+ - one in the parallel
+ - one in the low iteration count loop
Crucially, none for a peeled off last iteration following the parallel. */
-/* { dg-final { scan-tree-dump-times "(?n)\\\[i" 9 "parloops" } } */
+/* { dg-final { scan-tree-dump-times "(?n)^ \\*_\[0-9\]*" 3 "parloops" } } */
diff --git a/gcc/testsuite/gcc.target/arm/armv8-sync-comp-swap.c b/gcc/testsuite/gcc.target/arm/armv8-sync-comp-swap.c
new file mode 100644
index 00000000000..f96c81a8a9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/armv8-sync-comp-swap.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { do-require-effective-target arm_arch_v8a_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_arch_v8a } */
+
+#include "../aarch64/sync-comp-swap.x"
+
+/* { dg-final { scan-assembler-times "ldrex" 2 } } */
+/* { dg-final { scan-assembler-times "stlex" 2 } } */
+/* { dg-final { scan-assembler-times "dmb" 2 } } */
diff --git a/gcc/testsuite/gcc.target/arm/armv8-sync-op-acquire.c b/gcc/testsuite/gcc.target/arm/armv8-sync-op-acquire.c
new file mode 100644
index 00000000000..8d6659b70de
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/armv8-sync-op-acquire.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { do-require-effective-target arm_arch_v8a_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_arch_v8a } */
+
+#include "../aarch64/sync-op-acquire.x"
+
+/* { dg-final { scan-assembler-times "ldrex" 1 } } */
+/* { dg-final { scan-assembler-times "stlex" 1 } } */
+/* { dg-final { scan-assembler-times "dmb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/armv8-sync-op-full.c b/gcc/testsuite/gcc.target/arm/armv8-sync-op-full.c
new file mode 100644
index 00000000000..a5ad3bd822f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/armv8-sync-op-full.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { do-require-effective-target arm_arch_v8a_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_arch_v8a } */
+
+#include "../aarch64/sync-op-full.x"
+
+/* { dg-final { scan-assembler-times "ldrex" 12 } } */
+/* { dg-final { scan-assembler-times "stlex" 12 } } */
+/* { dg-final { scan-assembler-times "dmb" 12 } } */
diff --git a/gcc/testsuite/gcc.target/arm/armv8-sync-op-release.c b/gcc/testsuite/gcc.target/arm/armv8-sync-op-release.c
new file mode 100644
index 00000000000..0d3be7b8c0e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/armv8-sync-op-release.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { do-require-effective-target arm_arch_v8a_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_arch_v8a } */
+
+#include "../aarch64/sync-op-release.x"
+
+/* { dg-final { scan-assembler-times "stl" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/asm-flag-0.c b/gcc/testsuite/gcc.target/i386/asm-flag-0.c
new file mode 100644
index 00000000000..b0c05239b01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/asm-flag-0.c
@@ -0,0 +1,15 @@
+/* Test error conditions of asm flag outputs. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void a(void)
+{
+ char x;
+ asm("" : "=@cca,@ccc"(x)); /* { dg-error "alternatives not allowed" } */
+}
+
+void b(void)
+{
+ char x;
+ asm("" : "=@ccbad"(x)); /* { dg-error "unknown asm flag output" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/asm-flag-1.c b/gcc/testsuite/gcc.target/i386/asm-flag-1.c
new file mode 100644
index 00000000000..bcc4952239c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/asm-flag-1.c
@@ -0,0 +1,18 @@
+/* Test some of the valid @cc<cc> asm flag outputs. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+void f(char *out)
+{
+ asm("" : "=@cca"(out[0]), "=@ccc"(out[1]), "=@cce"(out[2]),
+ "=@ccg"(out[3]), "=@cco"(out[4]), "=@ccp"(out[5]),
+ "=@ccs"(out[6]));
+}
+
+/* { dg-final { scan-assembler "seta" } } */
+/* { dg-final { scan-assembler "setc" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "setg" } } */
+/* { dg-final { scan-assembler "seto" } } */
+/* { dg-final { scan-assembler "setp" } } */
+/* { dg-final { scan-assembler "sets" } } */
diff --git a/gcc/testsuite/gcc.target/i386/asm-flag-2.c b/gcc/testsuite/gcc.target/i386/asm-flag-2.c
new file mode 100644
index 00000000000..5f8fa13da98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/asm-flag-2.c
@@ -0,0 +1,16 @@
+/* Test some of the valid @cc<cc> asm flag outputs. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+void f(char *out)
+{
+ asm("" : "=@ccb"(out[0]), "=@ccl"(out[1]), "=@ccz"(out[2]),
+ "=@ccbe"(out[4]), "=@ccge"(out[5]), "=@ccle"(out[6]));
+}
+
+/* { dg-final { scan-assembler "setc" } } */
+/* { dg-final { scan-assembler "setl" } } */
+/* { dg-final { scan-assembler "sete" } } */
+/* { dg-final { scan-assembler "setna" } } */
+/* { dg-final { scan-assembler "setge" } } */
+/* { dg-final { scan-assembler "setle" } } */
diff --git a/gcc/testsuite/gcc.target/i386/asm-flag-3.c b/gcc/testsuite/gcc.target/i386/asm-flag-3.c
new file mode 100644
index 00000000000..220c07cb867
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/asm-flag-3.c
@@ -0,0 +1,22 @@
+/* Test some of the valid @cc<cc> asm flag outputs. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+#define DO(C) \
+void f##C(int *y) { char x; asm("" : "=@cc"#C(x)); if (!x) *y = 0; }
+
+DO(a)
+DO(c)
+DO(e)
+DO(g)
+DO(o)
+DO(p)
+DO(s)
+
+/* { dg-final { scan-assembler "ja" } } */
+/* { dg-final { scan-assembler "jc" } } */
+/* { dg-final { scan-assembler "je" } } */
+/* { dg-final { scan-assembler "jg" } } */
+/* { dg-final { scan-assembler "jo" } } */
+/* { dg-final { scan-assembler "jp" } } */
+/* { dg-final { scan-assembler "js" } } */
diff --git a/gcc/testsuite/gcc.target/i386/asm-flag-4.c b/gcc/testsuite/gcc.target/i386/asm-flag-4.c
new file mode 100644
index 00000000000..b84b7dfdb1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/asm-flag-4.c
@@ -0,0 +1,20 @@
+/* Test some of the valid @cc<cc> asm flag outputs. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+#define DO(C) \
+void f##C(int *y) { char x; asm("" : "=@cc"#C(x)); if (!x) *y = 0; }
+
+DO(b)
+DO(l)
+DO(z)
+DO(be)
+DO(ge)
+DO(le)
+
+/* { dg-final { scan-assembler "jc" } } */
+/* { dg-final { scan-assembler "jl" } } */
+/* { dg-final { scan-assembler "je" } } */
+/* { dg-final { scan-assembler "jna" } } */
+/* { dg-final { scan-assembler "jge" } } */
+/* { dg-final { scan-assembler "jle" } } */
diff --git a/gcc/testsuite/gcc.target/i386/asm-flag-5.c b/gcc/testsuite/gcc.target/i386/asm-flag-5.c
new file mode 100644
index 00000000000..151157daf41
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/asm-flag-5.c
@@ -0,0 +1,29 @@
+/* Test error conditions of asm flag outputs. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void f_B(void) { _Bool x; asm("" : "=@ccc"(x)); }
+void f_c(void) { char x; asm("" : "=@ccc"(x)); }
+void f_s(void) { short x; asm("" : "=@ccc"(x)); }
+void f_i(void) { int x; asm("" : "=@ccc"(x)); }
+void f_l(void) { long x; asm("" : "=@ccc"(x)); }
+
+void f_f(void)
+{
+ float x;
+ asm("" : "=@ccc"(x)); /* { dg-error invalid type } */
+}
+
+void f_d(void)
+{
+ double x;
+ asm("" : "=@ccc"(x)); /* { dg-error invalid type } */
+}
+
+struct S { int x[3]; };
+
+void f_S(void)
+{
+ struct S x;
+ asm("" : "=@ccc"(x)); /* { dg-error invalid type } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp b/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp
new file mode 100644
index 00000000000..b5b3261039a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/abi-iamcu.exp
@@ -0,0 +1,42 @@
+# Copyright (C) 2015 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/>.
+
+# The Intel MCU psABI testsuite needs one additional assembler file for
+# most testcases. For simplicity we will just link it into each test.
+
+load_lib c-torture.exp
+load_lib target-supports.exp
+load_lib torture-options.exp
+
+if { (![istarget x86_64-*-linux*] && ![istarget i?86-*-linux*])
+ || ![is-effective-target ia32] } then {
+ return
+}
+
+
+torture-init
+set-torture-options $C_TORTURE_OPTIONS
+set additional_flags "-miamcu -W -Wall -Wno-abi"
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
+ if {[runtest_file_p $runtests $src]} {
+ c-torture-execute [list $src \
+ $srcdir/$subdir/asm-support.S] \
+ $additional_flags
+ }
+}
+
+torture-finish
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/args.h b/gcc/testsuite/gcc.target/i386/iamcu/args.h
new file mode 100644
index 00000000000..f8abde40155
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/args.h
@@ -0,0 +1,77 @@
+#ifndef INCLUDED_ARGS_H
+#define INCLUDED_ARGS_H
+
+/* This defines the calling sequences for integers and floats. */
+#define I0 eax
+#define I1 edx
+#define I2 ecx
+
+typedef unsigned int size_t;
+
+extern void (*callthis)(void);
+extern unsigned long eax,ebx,ecx,edx,esi,edi,esp,ebp;
+extern unsigned long sret_eax;
+extern volatile unsigned long volatile_var;
+extern void snapshot (void);
+extern void snapshot_ret (void);
+extern void *iamcu_memset (void *, int, size_t);
+#define WRAP_CALL(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot)
+#define WRAP_RET(N) \
+ (callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
+
+/* Clear all scratch integer registers. */
+#define clear_int_hardware_registers \
+ asm __volatile__ ("xor %%eax, %%eax\n\t" \
+ "xor %%edx, %%edx\n\t" \
+ "xor %%ecx, %%ecx\n\t" \
+ ::: "eax", "edx", "ecx");
+
+/* Clear all scratch integer registers, excluding the one used to return
+ aggregate. */
+#define clear_non_sret_int_hardware_registers \
+ asm __volatile__ ("xor %%edx, %%ebx\n\t" \
+ "xor %%ecx, %%ecx\n\t" \
+ ::: "edx", "ecx");
+
+/* This is the list of registers available for passing arguments. Not all of
+ these are used or even really available. */
+struct IntegerRegisters
+{
+ unsigned long eax, ebx, ecx, edx, esi, edi;
+};
+
+/* Implemented in scalarargs.c */
+extern struct IntegerRegisters iregs, iregbits;
+extern unsigned int num_iregs;
+
+#define check_int_arguments do { \
+ assert (num_iregs <= 0 || (iregs.I0 & iregbits.I0) == (I0 & iregbits.I0)); \
+ assert (num_iregs <= 1 || (iregs.I1 & iregbits.I1) == (I1 & iregbits.I1)); \
+ assert (num_iregs <= 2 || (iregs.I2 & iregbits.I2) == (I2 & iregbits.I2)); \
+ } while (0)
+
+#define check_char_arguments check_int_arguments
+#define check_short_arguments check_int_arguments
+#define check_long_arguments check_int_arguments
+#define check_float_arguments check_int_arguments
+#define check_double_arguments check_int_arguments
+#define check_ldouble_arguments check_int_arguments
+
+/* Clear register struct. */
+#define clear_struct_registers \
+ eax = edx = ecx = 0; \
+ iamcu_memset (&iregs, 0, sizeof iregs);
+
+/* Clear both hardware and register structs for integers. */
+#define clear_int_registers \
+ clear_struct_registers \
+ clear_int_hardware_registers
+
+/* Clear both hardware and register structs for integers, excluding the
+ one used to return aggregate. */
+#define clear_non_sret_int_registers \
+ clear_struct_registers \
+ clear_non_sret_int_hardware_registers
+
+#endif /* INCLUDED_ARGS_H */
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S b/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S
new file mode 100644
index 00000000000..b4a4a140e54
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/asm-support.S
@@ -0,0 +1,302 @@
+ .comm callthis,4,4
+ .comm eax,4,4
+ .comm ebx,4,4
+ .comm ecx,4,4
+ .comm edx,4,4
+ .comm esi,4,4
+ .comm edi,4,4
+ .comm esp,4,4
+ .comm ebp,4,4
+ .comm sret_eax,4,4
+ .comm volatile_var,4,4
+
+ .text
+ .p2align 4,,15
+.globl snapshot
+ .type snapshot, @function
+snapshot:
+ movl %eax, eax
+ movl %ebx, ebx
+ movl %ecx, ecx
+ movl %edx, edx
+ movl %edi, edi
+ movl %esi, esi
+ movl %ebp, ebp
+ movl %esp, esp
+ jmp *callthis
+ .size snapshot, .-snapshot
+
+ .p2align 4,,15
+.globl snapshot_ret
+ .type snapshot_ret, @function
+snapshot_ret:
+ movl %eax, sret_eax
+ call *callthis
+ movl %eax, eax
+ movl %edx, edx
+ ret
+ .size snapshot_ret, .-snapshot_ret
+
+ .p2align 4,,15
+ .globl __nesf2
+ .type __nesf2, @function
+__nesf2:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ movl $1, %eax
+ fildl (%esp)
+ movl %edx, (%esp)
+ xorl %edx, %edx
+ fildl (%esp)
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __nesf2, .-__nesf2
+
+ .p2align 4,,15
+ .globl __nedf2
+ .type __nedf2, @function
+__nedf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ movl $1, %eax
+ movl %edx, 4(%esp)
+ xorl %edx, %edx
+ fildq (%esp)
+ fildq 8(%ebp)
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __nedf2, .-__nedf2
+
+ .p2align 4,,15
+ .globl __addsf3
+ .type __addsf3, @function
+__addsf3:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ flds (%esp)
+ movl %edx, (%esp)
+ flds (%esp)
+ faddp %st, %st(1)
+ fstps (%esp)
+ movl (%esp), %eax
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __addsf3, .-__addsf3
+
+ .p2align 4,,15
+ .globl __adddf3
+ .type __adddf3, @function
+__adddf3:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fldl (%esp)
+ faddl 8(%ebp)
+ fstpl (%esp)
+ movl (%esp), %eax
+ movl 4(%esp), %edx
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __adddf3, .-__adddf3
+
+ .p2align 4,,15
+ .globl __floatsisf
+ .type __floatsisf, @function
+__floatsisf:
+ .cfi_startproc
+ subl $4, %esp
+ .cfi_def_cfa_offset 8
+ movl %eax, (%esp)
+ fildl (%esp)
+ addl $4, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __floatsisf, .-__floatsisf
+
+ .p2align 4,,15
+ .globl __floatunsisf
+ .type __floatunsisf, @function
+__floatunsisf:
+ .cfi_startproc
+ subl $8, %esp
+ .cfi_def_cfa_offset 12
+ xorl %edx, %edx
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fildq (%esp)
+ addl $8, %esp
+ .cfi_def_cfa_offset 4
+ ret
+ .cfi_endproc
+ .size __floatunsisf, .-__floatunsisf
+
+ .globl __extendsfdf2
+ .type __extendsfdf2, @function
+__extendsfdf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $8, %esp
+ movl %eax, (%esp)
+ flds (%esp)
+ fstpl (%esp)
+ movl (%esp), %eax
+ movl 4(%esp), %edx
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __extendsfdf2, .-__extendsfdf2
+
+ .p2align 4,,15
+ .globl __truncdfsf2
+ .type __truncdfsf2, @function
+__truncdfsf2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ andl $-8, %esp
+ subl $12, %esp
+ movl %eax, (%esp)
+ movl %edx, 4(%esp)
+ fldl (%esp)
+ fstps (%esp)
+ movl (%esp), %eax
+ leave
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+ .size __truncdfsf2, .-__truncdfsf2
+
+ .p2align 4,,15
+ .globl iamcu_memset
+ .type iamcu_memset, @function
+iamcu_memset:
+ .cfi_startproc
+ pushl %edi
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset %edi, 0
+ movl %eax, %edi
+ movzbl %dl, %eax
+ movl %edi, %edx
+ rep stosb
+ movl %edx, %eax
+ popl %edi
+ .cfi_adjust_cfa_offset -4
+ .cfi_restore %edi
+ ret
+ .cfi_endproc
+ .size iamcu_memset, .-iamcu_memset
+
+ .p2align 4,,15
+ .globl iamcu_noprintf
+ .type iamcu_noprintf, @function
+iamcu_noprintf:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ cmpl $-1414676753, 8(%ebp)
+ fldl 16(%ebp)
+ fldl 28(%ebp)
+ jne 7f
+ cmpl $256, 12(%ebp)
+ jne 8f
+ flds .LCiamcu_noprintf0
+ movl $1, %eax
+ fucomip %st(2), %st
+ fstp %st(1)
+ setp %dl
+ cmovne %eax, %edx
+ testb %dl, %dl
+ jne 9f
+ cmpl $-1146241297, 24(%ebp)
+ jne 10f
+ flds .LCiamcu_noprintf1
+ fucomip %st(1), %st
+ fstp %st(0)
+ setp %dl
+ cmove %edx, %eax
+ testb %al, %al
+ jne 2f
+ cmpl $259, 36(%ebp)
+ jne 2f
+ popl %ebp
+ .cfi_remember_state
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+7:
+ .cfi_restore_state
+ fstp %st(0)
+ fstp %st(0)
+ jmp 2f
+8:
+ fstp %st(0)
+ fstp %st(0)
+ .p2align 4,,3
+ jmp 2f
+9:
+ fstp %st(0)
+ jmp 2f
+10:
+ fstp %st(0)
+2:
+ call abort
+ .cfi_endproc
+ .size iamcu_noprintf, .-iamcu_noprintf
+ .section .rodata.cst4,"aM",@progbits,4
+ .align 4
+.LCiamcu_noprintf0:
+ .long 1132494848
+ .align 4
+.LCiamcu_noprintf1:
+ .long 1132527616
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/defines.h b/gcc/testsuite/gcc.target/i386/iamcu/defines.h
new file mode 100644
index 00000000000..e715f4247f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/defines.h
@@ -0,0 +1,110 @@
+#ifndef DEFINED_DEFINES_H
+#define DEFINED_DEFINES_H
+
+typedef unsigned long long ulonglong;
+typedef long double ldouble;
+
+/* These defines determines what part of the test should be run. When
+ GCC implements these parts, the defines should be uncommented to
+ enable testing. */
+
+/* Scalar type long double. */
+#define CHECK_LONG_DOUBLE
+
+/* Scalar type __float128. */
+#define CHECK_FLOAT128
+
+/* Returning of complex type. */
+#define CHECK_COMPLEX
+
+/* Structs with size > 8. */
+#define CHECK_LARGER_STRUCTS
+
+/* Checks for passing floats and doubles. */
+#define CHECK_FLOAT_DOUBLE_PASSING
+
+/* Union passing with not-extremely-simple unions. */
+#define CHECK_LARGER_UNION_PASSING
+
+/* Variable args. */
+#define CHECK_VARARGS
+
+/* Check argument passing and returning for scalar types with sizeof > 8. */
+#define CHECK_LARGE_SCALAR_PASSING
+
+/* Defines for sizing and alignment. */
+
+#define TYPE_SIZE_CHAR 1
+#define TYPE_SIZE_SHORT 2
+#define TYPE_SIZE_INT 4
+#define TYPE_SIZE_LONG 4
+#define TYPE_SIZE_LONG_LONG 8
+#define TYPE_SIZE_FLOAT 4
+#define TYPE_SIZE_DOUBLE 8
+#define TYPE_SIZE_LONG_DOUBLE 8
+#define TYPE_SIZE_FLOAT128 16
+#define TYPE_SIZE_ENUM 4
+#define TYPE_SIZE_POINTER 4
+
+#define TYPE_ALIGN_CHAR 1
+#define TYPE_ALIGN_SHORT 2
+#define TYPE_ALIGN_INT 4
+#define TYPE_ALIGN_LONG 4
+#define TYPE_ALIGN_LONG_LONG 4
+#define TYPE_ALIGN_FLOAT 4
+#define TYPE_ALIGN_DOUBLE 4
+#define TYPE_ALIGN_LONG_DOUBLE 4
+#define TYPE_ALIGN_FLOAT128 4
+#define TYPE_ALIGN_ENUM 4
+#define TYPE_ALIGN_POINTER 4
+
+/* These defines control the building of the list of types to check. There
+ is a string identifying the type (with a comma after), a size of the type
+ (also with a comma and an integer for adding to the total amount of types)
+ and an alignment of the type (which is currently not really needed since
+ the abi specifies that alignof == sizeof for all scalar types). */
+#ifdef CHECK_LONG_DOUBLE
+#define CLD_STR "long double",
+#define CLD_SIZ TYPE_SIZE_LONG_DOUBLE,
+#define CLD_ALI TYPE_ALIGN_LONG_DOUBLE,
+#define CLD_RET "???",
+#else
+#define CLD_STR
+#define CLD_SIZ
+#define CLD_ALI
+#define CLD_RET
+#endif
+#ifdef CHECK_FLOAT128
+#define CF128_STR "__float128",
+#define CF128_SIZ TYPE_SIZE_FLOAT128,
+#define CF128_ALI TYPE_ALIGN_FLOAT128,
+#define CF128_RET "???",
+#else
+#define CF128_STR
+#define CF128_SIZ
+#define CF128_ALI
+#define CF128_RET
+#endif
+
+/* Used in size and alignment tests. */
+enum dummytype { enumtype };
+
+extern void abort (void);
+
+/* Assertion macro. */
+#define assert(test) if (!(test)) abort()
+
+#ifdef __GNUC__
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+
+#ifdef __GNUC__
+#define PACKED __attribute__((__packed__))
+#else
+#warning Some tests will fail due to missing __packed__ support
+#define PACKED
+#endif
+
+#endif /* DEFINED_DEFINES_H */
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/macros.h b/gcc/testsuite/gcc.target/i386/iamcu/macros.h
new file mode 100644
index 00000000000..98fbc660f27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/macros.h
@@ -0,0 +1,53 @@
+#ifndef MACROS_H
+
+#define check_size(_t, _size) assert(sizeof(_t) == (_size))
+
+#define check_align(_t, _align) assert(__alignof__(_t) == (_align))
+
+#define check_align_lv(_t, _align) assert(__alignof__(_t) == (_align) \
+ && (((unsigned long)&(_t)) & ((_align) - 1) ) == 0)
+
+#define check_basic_struct_size_and_align(_type, _size, _align) { \
+ struct _str { _type dummy; } _t; \
+ check_size(_t, _size); \
+ check_align_lv(_t, _align); \
+}
+
+#define check_array_size_and_align(_type, _size, _align) { \
+ _type _a[1]; _type _b[2]; _type _c[16]; \
+ struct _str { _type _a[1]; } _s; \
+ check_align_lv(_a[0], _align); \
+ check_size(_a, _size); \
+ check_size(_b, (_size*2)); \
+ check_size(_c, (_size*16)); \
+ check_size(_s, _size); \
+ check_align_lv(_s._a[0], _align); \
+}
+
+#define check_basic_union_size_and_align(_type, _size, _align) { \
+ union _union { _type dummy; } _u; \
+ check_size(_u, _size); \
+ check_align_lv(_u, _align); \
+}
+
+#define run_signed_tests2(_function, _arg1, _arg2) \
+ _function(_arg1, _arg2); \
+ _function(signed _arg1, _arg2); \
+ _function(unsigned _arg1, _arg2);
+
+#define run_signed_tests3(_function, _arg1, _arg2, _arg3) \
+ _function(_arg1, _arg2, _arg3); \
+ _function(signed _arg1, _arg2, _arg3); \
+ _function(unsigned _arg1, _arg2, _arg3);
+
+/* Check size of a struct and a union of three types. */
+
+#define check_struct_and_union3(type1, type2, type3, struct_size, align_size) \
+{ \
+ struct _str { type1 t1; type2 t2; type3 t3; } _t; \
+ union _uni { type1 t1; type2 t2; type3 t3; } _u; \
+ check_size(_t, struct_size); \
+ check_size(_u, align_size); \
+}
+
+#endif // MACROS_H
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c
new file mode 100644
index 00000000000..7bec2119934
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_3_element_struct_and_unions.c
@@ -0,0 +1,521 @@
+#include "defines.h"
+#include "macros.h"
+
+/* Check structs and unions of all permutations of 3 basic types. */
+int
+main (void)
+{
+ check_struct_and_union3(char, char, char, 3, 1);
+ check_struct_and_union3(char, char, short, 4, 2);
+ check_struct_and_union3(char, char, int, 8, 4);
+ check_struct_and_union3(char, char, long, 8, 4);
+ check_struct_and_union3(char, char, long long, 12, 8);
+ check_struct_and_union3(char, char, float, 8, 4);
+ check_struct_and_union3(char, char, double, 12, 8);
+ check_struct_and_union3(char, char, long double, 12, 8);
+ check_struct_and_union3(char, short, char, 6, 2);
+ check_struct_and_union3(char, short, short, 6, 2);
+ check_struct_and_union3(char, short, int, 8, 4);
+ check_struct_and_union3(char, short, long, 8, 4);
+ check_struct_and_union3(char, short, long long, 12, 8);
+ check_struct_and_union3(char, short, float, 8, 4);
+ check_struct_and_union3(char, short, double, 12, 8);
+ check_struct_and_union3(char, short, long double, 12, 8);
+ check_struct_and_union3(char, int, char, 12, 4);
+ check_struct_and_union3(char, int, short, 12, 4);
+ check_struct_and_union3(char, int, int, 12, 4);
+ check_struct_and_union3(char, int, long, 12, 4);
+ check_struct_and_union3(char, int, long long, 16, 8);
+ check_struct_and_union3(char, int, float, 12, 4);
+ check_struct_and_union3(char, int, double, 16, 8);
+ check_struct_and_union3(char, int, long double, 16, 8);
+ check_struct_and_union3(char, long, char, 12, 4);
+ check_struct_and_union3(char, long, short, 12, 4);
+ check_struct_and_union3(char, long, int, 12, 4);
+ check_struct_and_union3(char, long, long, 12, 4);
+ check_struct_and_union3(char, long, long long, 16, 8);
+ check_struct_and_union3(char, long, float, 12, 4);
+ check_struct_and_union3(char, long, double, 16, 8);
+ check_struct_and_union3(char, long, long double, 16, 8);
+ check_struct_and_union3(char, long long, char, 16, 8);
+ check_struct_and_union3(char, long long, short, 16, 8);
+ check_struct_and_union3(char, long long, int, 16, 8);
+ check_struct_and_union3(char, long long, long, 16, 8);
+ check_struct_and_union3(char, long long, long long, 20, 8);
+ check_struct_and_union3(char, long long, float, 16, 8);
+ check_struct_and_union3(char, long long, double, 20, 8);
+ check_struct_and_union3(char, long long, long double, 20, 8);
+ check_struct_and_union3(char, float, char, 12, 4);
+ check_struct_and_union3(char, float, short, 12, 4);
+ check_struct_and_union3(char, float, int, 12, 4);
+ check_struct_and_union3(char, float, long, 12, 4);
+ check_struct_and_union3(char, float, long long, 16, 8);
+ check_struct_and_union3(char, float, float, 12, 4);
+ check_struct_and_union3(char, float, double, 16, 8);
+ check_struct_and_union3(char, float, long double, 16, 8);
+ check_struct_and_union3(char, double, char, 16, 8);
+ check_struct_and_union3(char, double, short, 16, 8);
+ check_struct_and_union3(char, double, int, 16, 8);
+ check_struct_and_union3(char, double, long, 16, 8);
+ check_struct_and_union3(char, double, long long, 20, 8);
+ check_struct_and_union3(char, double, float, 16, 8);
+ check_struct_and_union3(char, double, double, 20, 8);
+ check_struct_and_union3(char, double, long double, 20, 8);
+ check_struct_and_union3(char, long double, char, 16, 8);
+ check_struct_and_union3(char, long double, short, 16, 8);
+ check_struct_and_union3(char, long double, int, 16, 8);
+ check_struct_and_union3(char, long double, long, 16, 8);
+ check_struct_and_union3(char, long double, long long, 20, 8);
+ check_struct_and_union3(char, long double, float, 16, 8);
+ check_struct_and_union3(char, long double, double, 20, 8);
+ check_struct_and_union3(char, long double, long double, 20, 8);
+ check_struct_and_union3(short, char, char, 4, 2);
+ check_struct_and_union3(short, char, short, 6, 2);
+ check_struct_and_union3(short, char, int, 8, 4);
+ check_struct_and_union3(short, char, long, 8, 4);
+ check_struct_and_union3(short, char, long long, 12, 8);
+ check_struct_and_union3(short, char, float, 8, 4);
+ check_struct_and_union3(short, char, double, 12, 8);
+ check_struct_and_union3(short, char, long double, 12, 8);
+ check_struct_and_union3(short, short, char, 6, 2);
+ check_struct_and_union3(short, short, short, 6, 2);
+ check_struct_and_union3(short, short, int, 8, 4);
+ check_struct_and_union3(short, short, long, 8, 4);
+ check_struct_and_union3(short, short, long long, 12, 8);
+ check_struct_and_union3(short, short, float, 8, 4);
+ check_struct_and_union3(short, short, double, 12, 8);
+ check_struct_and_union3(short, short, long double, 12, 8);
+ check_struct_and_union3(short, int, char, 12, 4);
+ check_struct_and_union3(short, int, short, 12, 4);
+ check_struct_and_union3(short, int, int, 12, 4);
+ check_struct_and_union3(short, int, long, 12, 4);
+ check_struct_and_union3(short, int, long long, 16, 8);
+ check_struct_and_union3(short, int, float, 12, 4);
+ check_struct_and_union3(short, int, double, 16, 8);
+ check_struct_and_union3(short, int, long double, 16, 8);
+ check_struct_and_union3(short, long, char, 12, 4);
+ check_struct_and_union3(short, long, short, 12, 4);
+ check_struct_and_union3(short, long, int, 12, 4);
+ check_struct_and_union3(short, long, long, 12, 4);
+ check_struct_and_union3(short, long, long long, 16, 8);
+ check_struct_and_union3(short, long, float, 12, 4);
+ check_struct_and_union3(short, long, double, 16, 8);
+ check_struct_and_union3(short, long, long double, 16, 8);
+ check_struct_and_union3(short, long long, char, 16, 8);
+ check_struct_and_union3(short, long long, short, 16, 8);
+ check_struct_and_union3(short, long long, int, 16, 8);
+ check_struct_and_union3(short, long long, long, 16, 8);
+ check_struct_and_union3(short, long long, long long, 20, 8);
+ check_struct_and_union3(short, long long, float, 16, 8);
+ check_struct_and_union3(short, long long, double, 20, 8);
+ check_struct_and_union3(short, long long, long double, 20, 8);
+ check_struct_and_union3(short, float, char, 12, 4);
+ check_struct_and_union3(short, float, short, 12, 4);
+ check_struct_and_union3(short, float, int, 12, 4);
+ check_struct_and_union3(short, float, long, 12, 4);
+ check_struct_and_union3(short, float, long long, 16, 8);
+ check_struct_and_union3(short, float, float, 12, 4);
+ check_struct_and_union3(short, float, double, 16, 8);
+ check_struct_and_union3(short, float, long double, 16, 8);
+ check_struct_and_union3(short, double, char, 16, 8);
+ check_struct_and_union3(short, double, short, 16, 8);
+ check_struct_and_union3(short, double, int, 16, 8);
+ check_struct_and_union3(short, double, long, 16, 8);
+ check_struct_and_union3(short, double, long long, 20, 8);
+ check_struct_and_union3(short, double, float, 16, 8);
+ check_struct_and_union3(short, double, double, 20, 8);
+ check_struct_and_union3(short, double, long double, 20, 8);
+ check_struct_and_union3(short, long double, char, 16, 8);
+ check_struct_and_union3(short, long double, short, 16, 8);
+ check_struct_and_union3(short, long double, int, 16, 8);
+ check_struct_and_union3(short, long double, long, 16, 8);
+ check_struct_and_union3(short, long double, long long, 20, 8);
+ check_struct_and_union3(short, long double, float, 16, 8);
+ check_struct_and_union3(short, long double, double, 20, 8);
+ check_struct_and_union3(short, long double, long double, 20, 8);
+ check_struct_and_union3(int, char, char, 8, 4);
+ check_struct_and_union3(int, char, short, 8, 4);
+ check_struct_and_union3(int, char, int, 12, 4);
+ check_struct_and_union3(int, char, long, 12, 4);
+ check_struct_and_union3(int, char, long long, 16, 8);
+ check_struct_and_union3(int, char, float, 12, 4);
+ check_struct_and_union3(int, char, double, 16, 8);
+ check_struct_and_union3(int, char, long double, 16, 8);
+ check_struct_and_union3(int, short, char, 8, 4);
+ check_struct_and_union3(int, short, short, 8, 4);
+ check_struct_and_union3(int, short, int, 12, 4);
+ check_struct_and_union3(int, short, long, 12, 4);
+ check_struct_and_union3(int, short, long long, 16, 8);
+ check_struct_and_union3(int, short, float, 12, 4);
+ check_struct_and_union3(int, short, double, 16, 8);
+ check_struct_and_union3(int, short, long double, 16, 8);
+ check_struct_and_union3(int, int, char, 12, 4);
+ check_struct_and_union3(int, int, short, 12, 4);
+ check_struct_and_union3(int, int, int, 12, 4);
+ check_struct_and_union3(int, int, long, 12, 4);
+ check_struct_and_union3(int, int, long long, 16, 8);
+ check_struct_and_union3(int, int, float, 12, 4);
+ check_struct_and_union3(int, int, double, 16, 8);
+ check_struct_and_union3(int, int, long double, 16, 8);
+ check_struct_and_union3(int, long, char, 12, 4);
+ check_struct_and_union3(int, long, short, 12, 4);
+ check_struct_and_union3(int, long, int, 12, 4);
+ check_struct_and_union3(int, long, long, 12, 4);
+ check_struct_and_union3(int, long, long long, 16, 8);
+ check_struct_and_union3(int, long, float, 12, 4);
+ check_struct_and_union3(int, long, double, 16, 8);
+ check_struct_and_union3(int, long, long double, 16, 8);
+ check_struct_and_union3(int, long long, char, 16, 8);
+ check_struct_and_union3(int, long long, short, 16, 8);
+ check_struct_and_union3(int, long long, int, 16, 8);
+ check_struct_and_union3(int, long long, long, 16, 8);
+ check_struct_and_union3(int, long long, long long, 20, 8);
+ check_struct_and_union3(int, long long, float, 16, 8);
+ check_struct_and_union3(int, long long, double, 20, 8);
+ check_struct_and_union3(int, long long, long double, 20, 8);
+ check_struct_and_union3(int, float, char, 12, 4);
+ check_struct_and_union3(int, float, short, 12, 4);
+ check_struct_and_union3(int, float, int, 12, 4);
+ check_struct_and_union3(int, float, long, 12, 4);
+ check_struct_and_union3(int, float, long long, 16, 8);
+ check_struct_and_union3(int, float, float, 12, 4);
+ check_struct_and_union3(int, float, double, 16, 8);
+ check_struct_and_union3(int, float, long double, 16, 8);
+ check_struct_and_union3(int, double, char, 16, 8);
+ check_struct_and_union3(int, double, short, 16, 8);
+ check_struct_and_union3(int, double, int, 16, 8);
+ check_struct_and_union3(int, double, long, 16, 8);
+ check_struct_and_union3(int, double, long long, 20, 8);
+ check_struct_and_union3(int, double, float, 16, 8);
+ check_struct_and_union3(int, double, double, 20, 8);
+ check_struct_and_union3(int, double, long double, 20, 8);
+ check_struct_and_union3(int, long double, char, 16, 8);
+ check_struct_and_union3(int, long double, short, 16, 8);
+ check_struct_and_union3(int, long double, int, 16, 8);
+ check_struct_and_union3(int, long double, long, 16, 8);
+ check_struct_and_union3(int, long double, long long, 20, 8);
+ check_struct_and_union3(int, long double, float, 16, 8);
+ check_struct_and_union3(int, long double, double, 20, 8);
+ check_struct_and_union3(int, long double, long double, 20, 8);
+ check_struct_and_union3(long, char, char, 8, 4);
+ check_struct_and_union3(long, char, short, 8, 4);
+ check_struct_and_union3(long, char, int, 12, 4);
+ check_struct_and_union3(long, char, long, 12, 4);
+ check_struct_and_union3(long, char, long long, 16, 8);
+ check_struct_and_union3(long, char, float, 12, 4);
+ check_struct_and_union3(long, char, double, 16, 8);
+ check_struct_and_union3(long, char, long double, 16, 8);
+ check_struct_and_union3(long, short, char, 8, 4);
+ check_struct_and_union3(long, short, short, 8, 4);
+ check_struct_and_union3(long, short, int, 12, 4);
+ check_struct_and_union3(long, short, long, 12, 4);
+ check_struct_and_union3(long, short, long long, 16, 8);
+ check_struct_and_union3(long, short, float, 12, 4);
+ check_struct_and_union3(long, short, double, 16, 8);
+ check_struct_and_union3(long, short, long double, 16, 8);
+ check_struct_and_union3(long, int, char, 12, 4);
+ check_struct_and_union3(long, int, short, 12, 4);
+ check_struct_and_union3(long, int, int, 12, 4);
+ check_struct_and_union3(long, int, long, 12, 4);
+ check_struct_and_union3(long, int, long long, 16, 8);
+ check_struct_and_union3(long, int, float, 12, 4);
+ check_struct_and_union3(long, int, double, 16, 8);
+ check_struct_and_union3(long, int, long double, 16, 8);
+ check_struct_and_union3(long, long, char, 12, 4);
+ check_struct_and_union3(long, long, short, 12, 4);
+ check_struct_and_union3(long, long, int, 12, 4);
+ check_struct_and_union3(long, long, long, 12, 4);
+ check_struct_and_union3(long, long, long long, 16, 8);
+ check_struct_and_union3(long, long, float, 12, 4);
+ check_struct_and_union3(long, long, double, 16, 8);
+ check_struct_and_union3(long, long, long double, 16, 8);
+ check_struct_and_union3(long, long long, char, 16, 8);
+ check_struct_and_union3(long, long long, short, 16, 8);
+ check_struct_and_union3(long, long long, int, 16, 8);
+ check_struct_and_union3(long, long long, long, 16, 8);
+ check_struct_and_union3(long, long long, long long, 20, 8);
+ check_struct_and_union3(long, long long, float, 16, 8);
+ check_struct_and_union3(long, long long, double, 20, 8);
+ check_struct_and_union3(long, long long, long double, 20, 8);
+ check_struct_and_union3(long, float, char, 12, 4);
+ check_struct_and_union3(long, float, short, 12, 4);
+ check_struct_and_union3(long, float, int, 12, 4);
+ check_struct_and_union3(long, float, long, 12, 4);
+ check_struct_and_union3(long, float, long long, 16, 8);
+ check_struct_and_union3(long, float, float, 12, 4);
+ check_struct_and_union3(long, float, double, 16, 8);
+ check_struct_and_union3(long, float, long double, 16, 8);
+ check_struct_and_union3(long, double, char, 16, 8);
+ check_struct_and_union3(long, double, short, 16, 8);
+ check_struct_and_union3(long, double, int, 16, 8);
+ check_struct_and_union3(long, double, long, 16, 8);
+ check_struct_and_union3(long, double, long long, 20, 8);
+ check_struct_and_union3(long, double, float, 16, 8);
+ check_struct_and_union3(long, double, double, 20, 8);
+ check_struct_and_union3(long, double, long double, 20, 8);
+ check_struct_and_union3(long, long double, char, 16, 8);
+ check_struct_and_union3(long, long double, short, 16, 8);
+ check_struct_and_union3(long, long double, int, 16, 8);
+ check_struct_and_union3(long, long double, long, 16, 8);
+ check_struct_and_union3(long, long double, long long, 20, 8);
+ check_struct_and_union3(long, long double, float, 16, 8);
+ check_struct_and_union3(long, long double, double, 20, 8);
+ check_struct_and_union3(long, long double, long double, 20, 8);
+ check_struct_and_union3(long long, char, char, 12, 8);
+ check_struct_and_union3(long long, char, short, 12, 8);
+ check_struct_and_union3(long long, char, int, 16, 8);
+ check_struct_and_union3(long long, char, long, 16, 8);
+ check_struct_and_union3(long long, char, long long, 20, 8);
+ check_struct_and_union3(long long, char, float, 16, 8);
+ check_struct_and_union3(long long, char, double, 20, 8);
+ check_struct_and_union3(long long, char, long double, 20, 8);
+ check_struct_and_union3(long long, short, char, 12, 8);
+ check_struct_and_union3(long long, short, short, 12, 8);
+ check_struct_and_union3(long long, short, int, 16, 8);
+ check_struct_and_union3(long long, short, long, 16, 8);
+ check_struct_and_union3(long long, short, long long, 20, 8);
+ check_struct_and_union3(long long, short, float, 16, 8);
+ check_struct_and_union3(long long, short, double, 20, 8);
+ check_struct_and_union3(long long, short, long double, 20, 8);
+ check_struct_and_union3(long long, int, char, 16, 8);
+ check_struct_and_union3(long long, int, short, 16, 8);
+ check_struct_and_union3(long long, int, int, 16, 8);
+ check_struct_and_union3(long long, int, long, 16, 8);
+ check_struct_and_union3(long long, int, long long, 20, 8);
+ check_struct_and_union3(long long, int, float, 16, 8);
+ check_struct_and_union3(long long, int, double, 20, 8);
+ check_struct_and_union3(long long, int, long double, 20, 8);
+ check_struct_and_union3(long long, long, char, 16, 8);
+ check_struct_and_union3(long long, long, short, 16, 8);
+ check_struct_and_union3(long long, long, int, 16, 8);
+ check_struct_and_union3(long long, long, long, 16, 8);
+ check_struct_and_union3(long long, long, long long, 20, 8);
+ check_struct_and_union3(long long, long, float, 16, 8);
+ check_struct_and_union3(long long, long, double, 20, 8);
+ check_struct_and_union3(long long, long, long double, 20, 8);
+ check_struct_and_union3(long long, long long, char, 20, 8);
+ check_struct_and_union3(long long, long long, short, 20, 8);
+ check_struct_and_union3(long long, long long, int, 20, 8);
+ check_struct_and_union3(long long, long long, long, 20, 8);
+ check_struct_and_union3(long long, long long, long long, 24, 8);
+ check_struct_and_union3(long long, long long, float, 20, 8);
+ check_struct_and_union3(long long, long long, double, 24, 8);
+ check_struct_and_union3(long long, long long, long double, 24, 8);
+ check_struct_and_union3(long long, float, char, 16, 8);
+ check_struct_and_union3(long long, float, short, 16, 8);
+ check_struct_and_union3(long long, float, int, 16, 8);
+ check_struct_and_union3(long long, float, long, 16, 8);
+ check_struct_and_union3(long long, float, long long, 20, 8);
+ check_struct_and_union3(long long, float, float, 16, 8);
+ check_struct_and_union3(long long, float, double, 20, 8);
+ check_struct_and_union3(long long, float, long double, 20, 8);
+ check_struct_and_union3(long long, double, char, 20, 8);
+ check_struct_and_union3(long long, double, short, 20, 8);
+ check_struct_and_union3(long long, double, int, 20, 8);
+ check_struct_and_union3(long long, double, long, 20, 8);
+ check_struct_and_union3(long long, double, long long, 24, 8);
+ check_struct_and_union3(long long, double, float, 20, 8);
+ check_struct_and_union3(long long, double, double, 24, 8);
+ check_struct_and_union3(long long, double, long double, 24, 8);
+ check_struct_and_union3(long long, long double, char, 20, 8);
+ check_struct_and_union3(long long, long double, short, 20, 8);
+ check_struct_and_union3(long long, long double, int, 20, 8);
+ check_struct_and_union3(long long, long double, long, 20, 8);
+ check_struct_and_union3(long long, long double, long long, 24, 8);
+ check_struct_and_union3(long long, long double, float, 20, 8);
+ check_struct_and_union3(long long, long double, double, 24, 8);
+ check_struct_and_union3(long long, long double, long double, 24, 8);
+ check_struct_and_union3(float, char, char, 8, 4);
+ check_struct_and_union3(float, char, short, 8, 4);
+ check_struct_and_union3(float, char, int, 12, 4);
+ check_struct_and_union3(float, char, long, 12, 4);
+ check_struct_and_union3(float, char, long long, 16, 8);
+ check_struct_and_union3(float, char, float, 12, 4);
+ check_struct_and_union3(float, char, double, 16, 8);
+ check_struct_and_union3(float, char, long double, 16, 8);
+ check_struct_and_union3(float, short, char, 8, 4);
+ check_struct_and_union3(float, short, short, 8, 4);
+ check_struct_and_union3(float, short, int, 12, 4);
+ check_struct_and_union3(float, short, long, 12, 4);
+ check_struct_and_union3(float, short, long long, 16, 8);
+ check_struct_and_union3(float, short, float, 12, 4);
+ check_struct_and_union3(float, short, double, 16, 8);
+ check_struct_and_union3(float, short, long double, 16, 8);
+ check_struct_and_union3(float, int, char, 12, 4);
+ check_struct_and_union3(float, int, short, 12, 4);
+ check_struct_and_union3(float, int, int, 12, 4);
+ check_struct_and_union3(float, int, long, 12, 4);
+ check_struct_and_union3(float, int, long long, 16, 8);
+ check_struct_and_union3(float, int, float, 12, 4);
+ check_struct_and_union3(float, int, double, 16, 8);
+ check_struct_and_union3(float, int, long double, 16, 8);
+ check_struct_and_union3(float, long, char, 12, 4);
+ check_struct_and_union3(float, long, short, 12, 4);
+ check_struct_and_union3(float, long, int, 12, 4);
+ check_struct_and_union3(float, long, long, 12, 4);
+ check_struct_and_union3(float, long, long long, 16, 8);
+ check_struct_and_union3(float, long, float, 12, 4);
+ check_struct_and_union3(float, long, double, 16, 8);
+ check_struct_and_union3(float, long, long double, 16, 8);
+ check_struct_and_union3(float, long long, char, 16, 8);
+ check_struct_and_union3(float, long long, short, 16, 8);
+ check_struct_and_union3(float, long long, int, 16, 8);
+ check_struct_and_union3(float, long long, long, 16, 8);
+ check_struct_and_union3(float, long long, long long, 20, 8);
+ check_struct_and_union3(float, long long, float, 16, 8);
+ check_struct_and_union3(float, long long, double, 20, 8);
+ check_struct_and_union3(float, long long, long double, 20, 8);
+ check_struct_and_union3(float, float, char, 12, 4);
+ check_struct_and_union3(float, float, short, 12, 4);
+ check_struct_and_union3(float, float, int, 12, 4);
+ check_struct_and_union3(float, float, long, 12, 4);
+ check_struct_and_union3(float, float, long long, 16, 8);
+ check_struct_and_union3(float, float, float, 12, 4);
+ check_struct_and_union3(float, float, double, 16, 8);
+ check_struct_and_union3(float, float, long double, 16, 8);
+ check_struct_and_union3(float, double, char, 16, 8);
+ check_struct_and_union3(float, double, short, 16, 8);
+ check_struct_and_union3(float, double, int, 16, 8);
+ check_struct_and_union3(float, double, long, 16, 8);
+ check_struct_and_union3(float, double, long long, 20, 8);
+ check_struct_and_union3(float, double, float, 16, 8);
+ check_struct_and_union3(float, double, double, 20, 8);
+ check_struct_and_union3(float, double, long double, 20, 8);
+ check_struct_and_union3(float, long double, char, 16, 8);
+ check_struct_and_union3(float, long double, short, 16, 8);
+ check_struct_and_union3(float, long double, int, 16, 8);
+ check_struct_and_union3(float, long double, long, 16, 8);
+ check_struct_and_union3(float, long double, long long, 20, 8);
+ check_struct_and_union3(float, long double, float, 16, 8);
+ check_struct_and_union3(float, long double, double, 20, 8);
+ check_struct_and_union3(float, long double, long double, 20, 8);
+ check_struct_and_union3(double, char, char, 12, 8);
+ check_struct_and_union3(double, char, short, 12, 8);
+ check_struct_and_union3(double, char, int, 16, 8);
+ check_struct_and_union3(double, char, long, 16, 8);
+ check_struct_and_union3(double, char, long long, 20, 8);
+ check_struct_and_union3(double, char, float, 16, 8);
+ check_struct_and_union3(double, char, double, 20, 8);
+ check_struct_and_union3(double, char, long double, 20, 8);
+ check_struct_and_union3(double, short, char, 12, 8);
+ check_struct_and_union3(double, short, short, 12, 8);
+ check_struct_and_union3(double, short, int, 16, 8);
+ check_struct_and_union3(double, short, long, 16, 8);
+ check_struct_and_union3(double, short, long long, 20, 8);
+ check_struct_and_union3(double, short, float, 16, 8);
+ check_struct_and_union3(double, short, double, 20, 8);
+ check_struct_and_union3(double, short, long double, 20, 8);
+ check_struct_and_union3(double, int, char, 16, 8);
+ check_struct_and_union3(double, int, short, 16, 8);
+ check_struct_and_union3(double, int, int, 16, 8);
+ check_struct_and_union3(double, int, long, 16, 8);
+ check_struct_and_union3(double, int, long long, 20, 8);
+ check_struct_and_union3(double, int, float, 16, 8);
+ check_struct_and_union3(double, int, double, 20, 8);
+ check_struct_and_union3(double, int, long double, 20, 8);
+ check_struct_and_union3(double, long, char, 16, 8);
+ check_struct_and_union3(double, long, short, 16, 8);
+ check_struct_and_union3(double, long, int, 16, 8);
+ check_struct_and_union3(double, long, long, 16, 8);
+ check_struct_and_union3(double, long, long long, 20, 8);
+ check_struct_and_union3(double, long, float, 16, 8);
+ check_struct_and_union3(double, long, double, 20, 8);
+ check_struct_and_union3(double, long, long double, 20, 8);
+ check_struct_and_union3(double, long long, char, 20, 8);
+ check_struct_and_union3(double, long long, short, 20, 8);
+ check_struct_and_union3(double, long long, int, 20, 8);
+ check_struct_and_union3(double, long long, long, 20, 8);
+ check_struct_and_union3(double, long long, long long, 24, 8);
+ check_struct_and_union3(double, long long, float, 20, 8);
+ check_struct_and_union3(double, long long, double, 24, 8);
+ check_struct_and_union3(double, long long, long double, 24, 8);
+ check_struct_and_union3(double, float, char, 16, 8);
+ check_struct_and_union3(double, float, short, 16, 8);
+ check_struct_and_union3(double, float, int, 16, 8);
+ check_struct_and_union3(double, float, long, 16, 8);
+ check_struct_and_union3(double, float, long long, 20, 8);
+ check_struct_and_union3(double, float, float, 16, 8);
+ check_struct_and_union3(double, float, double, 20, 8);
+ check_struct_and_union3(double, float, long double, 20, 8);
+ check_struct_and_union3(double, double, char, 20, 8);
+ check_struct_and_union3(double, double, short, 20, 8);
+ check_struct_and_union3(double, double, int, 20, 8);
+ check_struct_and_union3(double, double, long, 20, 8);
+ check_struct_and_union3(double, double, long long, 24, 8);
+ check_struct_and_union3(double, double, float, 20, 8);
+ check_struct_and_union3(double, double, double, 24, 8);
+ check_struct_and_union3(double, double, long double, 24, 8);
+ check_struct_and_union3(double, long double, char, 20, 8);
+ check_struct_and_union3(double, long double, short, 20, 8);
+ check_struct_and_union3(double, long double, int, 20, 8);
+ check_struct_and_union3(double, long double, long, 20, 8);
+ check_struct_and_union3(double, long double, long long, 24, 8);
+ check_struct_and_union3(double, long double, float, 20, 8);
+ check_struct_and_union3(double, long double, double, 24, 8);
+ check_struct_and_union3(double, long double, long double, 24, 8);
+ check_struct_and_union3(long double, char, char, 12, 8);
+ check_struct_and_union3(long double, char, short, 12, 8);
+ check_struct_and_union3(long double, char, int, 16, 8);
+ check_struct_and_union3(long double, char, long, 16, 8);
+ check_struct_and_union3(long double, char, long long, 20, 8);
+ check_struct_and_union3(long double, char, float, 16, 8);
+ check_struct_and_union3(long double, char, double, 20, 8);
+ check_struct_and_union3(long double, char, long double, 20, 8);
+ check_struct_and_union3(long double, short, char, 12, 8);
+ check_struct_and_union3(long double, short, short, 12, 8);
+ check_struct_and_union3(long double, short, int, 16, 8);
+ check_struct_and_union3(long double, short, long, 16, 8);
+ check_struct_and_union3(long double, short, long long, 20, 8);
+ check_struct_and_union3(long double, short, float, 16, 8);
+ check_struct_and_union3(long double, short, double, 20, 8);
+ check_struct_and_union3(long double, short, long double, 20, 8);
+ check_struct_and_union3(long double, int, char, 16, 8);
+ check_struct_and_union3(long double, int, short, 16, 8);
+ check_struct_and_union3(long double, int, int, 16, 8);
+ check_struct_and_union3(long double, int, long, 16, 8);
+ check_struct_and_union3(long double, int, long long, 20, 8);
+ check_struct_and_union3(long double, int, float, 16, 8);
+ check_struct_and_union3(long double, int, double, 20, 8);
+ check_struct_and_union3(long double, int, long double, 20, 8);
+ check_struct_and_union3(long double, long, char, 16, 8);
+ check_struct_and_union3(long double, long, short, 16, 8);
+ check_struct_and_union3(long double, long, int, 16, 8);
+ check_struct_and_union3(long double, long, long, 16, 8);
+ check_struct_and_union3(long double, long, long long, 20, 8);
+ check_struct_and_union3(long double, long, float, 16, 8);
+ check_struct_and_union3(long double, long, double, 20, 8);
+ check_struct_and_union3(long double, long, long double, 20, 8);
+ check_struct_and_union3(long double, long long, char, 20, 8);
+ check_struct_and_union3(long double, long long, short, 20, 8);
+ check_struct_and_union3(long double, long long, int, 20, 8);
+ check_struct_and_union3(long double, long long, long, 20, 8);
+ check_struct_and_union3(long double, long long, long long, 24, 8);
+ check_struct_and_union3(long double, long long, float, 20, 8);
+ check_struct_and_union3(long double, long long, double, 24, 8);
+ check_struct_and_union3(long double, long long, long double, 24, 8);
+ check_struct_and_union3(long double, float, char, 16, 8);
+ check_struct_and_union3(long double, float, short, 16, 8);
+ check_struct_and_union3(long double, float, int, 16, 8);
+ check_struct_and_union3(long double, float, long, 16, 8);
+ check_struct_and_union3(long double, float, long long, 20, 8);
+ check_struct_and_union3(long double, float, float, 16, 8);
+ check_struct_and_union3(long double, float, double, 20, 8);
+ check_struct_and_union3(long double, float, long double, 20, 8);
+ check_struct_and_union3(long double, double, char, 20, 8);
+ check_struct_and_union3(long double, double, short, 20, 8);
+ check_struct_and_union3(long double, double, int, 20, 8);
+ check_struct_and_union3(long double, double, long, 20, 8);
+ check_struct_and_union3(long double, double, long long, 24, 8);
+ check_struct_and_union3(long double, double, float, 20, 8);
+ check_struct_and_union3(long double, double, double, 24, 8);
+ check_struct_and_union3(long double, double, long double, 24, 8);
+ check_struct_and_union3(long double, long double, char, 20, 8);
+ check_struct_and_union3(long double, long double, short, 20, 8);
+ check_struct_and_union3(long double, long double, int, 20, 8);
+ check_struct_and_union3(long double, long double, long, 20, 8);
+ check_struct_and_union3(long double, long double, long long, 24, 8);
+ check_struct_and_union3(long double, long double, float, 20, 8);
+ check_struct_and_union3(long double, long double, double, 24, 8);
+ check_struct_and_union3(long double, long double, long double, 24, 8);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c
new file mode 100644
index 00000000000..ecece94b793
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_64bit_returning.c
@@ -0,0 +1,57 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+long long
+fun_test_returning_long_long (void)
+{
+ volatile_var++;
+ return (long long) 0xabadbeefabadbeefLL;
+}
+
+double
+fun_test_returning_double (void)
+{
+ volatile_var++;
+ return (double) 12345678.0;
+}
+
+union
+{
+ long long ll;
+ double d;
+} test_64;
+
+int
+main (void)
+{
+ unsigned failed = 0;
+ long long ll;
+ double d;
+
+ clear_struct_registers;
+ test_64.ll = 0xabadbeefabadbeefLL;
+
+ ll = WRAP_RET (fun_test_returning_long_long)();
+ if (ll != test_64.ll
+ || (test_64.ll & 0xffffffff) != eax
+ || ((test_64.ll >> 32) & 0xffffffff) != edx)
+ failed++;
+
+ clear_struct_registers;
+ test_64.d = 12345678.0;
+
+ d = WRAP_RET (fun_test_returning_double)();
+ if (d != test_64.d
+ || (test_64.ll & 0xffffffff) != eax
+ || ((test_64.ll >> 32) & 0xffffffff) != edx)
+ printf ("fail double\n"), failed++;
+
+ if (failed)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c
new file mode 100644
index 00000000000..f14cf170236
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_alignment.c
@@ -0,0 +1,33 @@
+/* This checks alignment of basic types. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests2(check_align, char, TYPE_ALIGN_CHAR);
+ run_signed_tests2(check_align, short, TYPE_ALIGN_SHORT);
+ run_signed_tests2(check_align, int, TYPE_ALIGN_INT);
+ run_signed_tests2(check_align, long, TYPE_ALIGN_LONG);
+ run_signed_tests2(check_align, long long, TYPE_ALIGN_LONG_LONG);
+ check_align(enumtype, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_align(float, TYPE_ALIGN_FLOAT);
+ check_align(double, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_align(long double, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_align(__float128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. */
+ check_align(void *, TYPE_ALIGN_POINTER);
+ check_align(void (*)(), TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c
new file mode 100644
index 00000000000..e4b6369c19a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_array_size_and_align.c
@@ -0,0 +1,32 @@
+/* Test of simple arrays, size and alignment. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_array_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_array_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_array_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_array_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_array_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_array_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_array_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_array_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_array_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_array_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_array_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c
new file mode 100644
index 00000000000..23efa6e5c01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_returning.c
@@ -0,0 +1,52 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+char
+fun_test_returning_char (void)
+{
+ volatile_var++;
+ return 64;
+}
+
+short
+fun_test_returning_short (void)
+{
+ volatile_var++;
+ return 65;
+}
+
+int
+fun_test_returning_int (void)
+{
+ volatile_var++;
+ return 66;
+}
+
+long
+fun_test_returning_long (void)
+{
+ volatile_var++;
+ return 67;
+}
+
+float
+fun_test_returning_float (void)
+{
+ volatile_var++;
+ return 68;
+}
+
+#define def_test_returning_type(fun, type, ret, reg) \
+ { type var = WRAP_RET (fun) (); \
+ assert (ret == (type) reg && ret == var); }
+int
+main (void)
+{
+ def_test_returning_type(fun_test_returning_char, char, 64, eax);
+ def_test_returning_type(fun_test_returning_short, short, 65, eax);
+ def_test_returning_type(fun_test_returning_int, int, 66, eax);
+ def_test_returning_type(fun_test_returning_long, long, 67, eax);
+ def_test_returning_type(fun_test_returning_float, float, 68, eax);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c
new file mode 100644
index 00000000000..6582fc638a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_sizes.c
@@ -0,0 +1,36 @@
+/* This checks sizes of basic types. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests2(check_size, char, TYPE_SIZE_CHAR);
+ run_signed_tests2(check_size, short, TYPE_SIZE_SHORT);
+ run_signed_tests2(check_size, int, TYPE_SIZE_INT);
+ run_signed_tests2(check_size, long, TYPE_SIZE_LONG);
+ run_signed_tests2(check_size, long long, TYPE_SIZE_LONG_LONG);
+#ifdef CHECK_INT128
+ run_signed_tests2(check_size, __int128, TYPE_SIZE_INT128);
+#endif
+ check_size(enumtype, TYPE_SIZE_ENUM);
+
+ /* Floating point types. */
+ check_size(float, TYPE_SIZE_FLOAT);
+ check_size(double, TYPE_SIZE_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_size(long double, TYPE_SIZE_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_size(__float128, TYPE_SIZE_FLOAT128);
+#endif
+
+ /* Pointer types. */
+ check_size(void *, TYPE_SIZE_POINTER);
+ check_size(void (*)(), TYPE_SIZE_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c
new file mode 100644
index 00000000000..3b5027ffaaf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_struct_size_and_align.c
@@ -0,0 +1,33 @@
+/* This checks size and alignment of structs with a single basic type
+ element. All basic types are checked. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_basic_struct_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_basic_struct_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_basic_struct_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_basic_struct_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_basic_struct_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_basic_struct_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_basic_struct_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_basic_struct_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_basic_struct_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_basic_struct_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_basic_struct_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c
new file mode 100644
index 00000000000..93ba5ffb8d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_basic_union_size_and_align.c
@@ -0,0 +1,32 @@
+/* Test of simple unions, size and alignment. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+int
+main (void)
+{
+ /* Integral types. */
+ run_signed_tests3(check_basic_union_size_and_align, char, TYPE_SIZE_CHAR, TYPE_ALIGN_CHAR);
+ run_signed_tests3(check_basic_union_size_and_align, short, TYPE_SIZE_SHORT, TYPE_ALIGN_SHORT);
+ run_signed_tests3(check_basic_union_size_and_align, int, TYPE_SIZE_INT, TYPE_ALIGN_INT);
+ run_signed_tests3(check_basic_union_size_and_align, long, TYPE_SIZE_LONG, TYPE_ALIGN_LONG);
+ run_signed_tests3(check_basic_union_size_and_align, long long, TYPE_SIZE_LONG_LONG, TYPE_ALIGN_LONG_LONG);
+ check_basic_union_size_and_align(enum dummytype, TYPE_SIZE_ENUM, TYPE_ALIGN_ENUM);
+
+ /* Floating point types. */
+ check_basic_union_size_and_align(float, TYPE_SIZE_FLOAT, TYPE_ALIGN_FLOAT);
+ check_basic_union_size_and_align(double, TYPE_SIZE_DOUBLE, TYPE_ALIGN_DOUBLE);
+#ifdef CHECK_LONG_DOUBLE
+ check_basic_union_size_and_align(long double, TYPE_SIZE_LONG_DOUBLE, TYPE_ALIGN_LONG_DOUBLE);
+#endif
+#ifdef CHECK_FLOAT128
+ check_basic_union_size_and_align(__float128, TYPE_SIZE_FLOAT128, TYPE_ALIGN_FLOAT128);
+#endif
+
+ /* Pointer types. The function pointer doesn't work with these macros. */
+ check_basic_union_size_and_align(void *, TYPE_SIZE_POINTER, TYPE_ALIGN_POINTER);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c b/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c
new file mode 100644
index 00000000000..0b1c29333dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_bitfields.c
@@ -0,0 +1,162 @@
+/* This is a small test to see if bitfields are working. It is only a
+ few structs and a union and a test to see if they have the correct
+ size, if values can be read and written and a couple of argument
+ passing tests. No alignment testing is done. */
+
+#include "defines.h"
+#include "macros.h"
+
+
+/* These five bitfields are taken from the System V ABI, Intel 386
+ architecture supplement. */
+
+/* Word aligned, sizeof is 4. */
+struct RightToLeft
+{
+ int j:5;
+ int k:6;
+ int m:7;
+};
+
+/* Word aligned, sizeof is 12. */
+struct BoundaryAlignment
+{
+ short s:9;
+ int j:9;
+ char c;
+ short t:9;
+ short u:9;
+ char d;
+};
+
+/* Halfword aligned, sizeof is 2. */
+struct StorageUnitSharing
+{
+ char c;
+ short s:8;
+};
+
+/* Halfword aligned, sizeof is 2. */
+union Allocation
+{
+ char c;
+ short s:8;
+};
+
+/* Byte aligned, sizeof is 9. */
+struct Unnamed
+{
+ char c;
+ int :0;
+ char d;
+ short :9;
+ char e;
+ char :0;
+};
+
+/* Extra struct testing bitfields in larger types.
+ Doubleword aligned, sizeof is 8. */
+struct LargerTypes
+{
+ long long l:33;
+ int i:31;
+};
+
+
+void
+passing1 (struct RightToLeft str, int j, int k, int m)
+{
+ assert (str.j == j);
+ assert (str.k == k);
+ assert (str.m == m);
+}
+
+void
+passing2 (struct BoundaryAlignment str, short s, int j, char c, short t,
+ short u, char d)
+{
+ assert (str.s == s);
+ assert (str.j == j);
+ assert (str.c == c);
+ assert (str.t == t);
+ assert (str.u == u);
+ assert (str.d == d);
+}
+
+void
+passing3 (struct StorageUnitSharing str, char c, short s)
+{
+ assert (str.c == c);
+ assert (str.s == s);
+}
+
+void
+passing4 (struct Unnamed str, char c, char d, char e)
+{
+ assert (str.c == c);
+ assert (str.d == d);
+ assert (str.e == e);
+}
+
+void
+passing5 (struct LargerTypes str, long long l, int i)
+{
+ assert (str.l == l);
+ assert (str.i == i);
+}
+
+
+void
+passingU (union Allocation u, char c)
+{
+ assert (u.c == c);
+ assert (u.s == c);
+}
+
+
+int
+main (void)
+{
+ struct RightToLeft str1;
+ struct BoundaryAlignment str2;
+ struct StorageUnitSharing str3;
+ struct Unnamed str4;
+ struct LargerTypes str5;
+ union Allocation u;
+
+ /* Check sizeof's. */
+ check_size(str1, 4);
+ check_size(str2, 12);
+ check_size(str3, 2);
+ check_size(str4, 9);
+ check_size(str5, 8);
+ check_size(u, 2);
+
+ /* Check alignof's. */
+ check_align_lv(str1, 4);
+ check_align_lv(str2, 4);
+ check_align_lv(str3, 2);
+ check_align_lv(str4, 1);
+ check_align_lv(str5, 4);
+ check_align_lv(u, 2);
+
+ /* Check passing. */
+ str1.j = str2.s = str3.c = str4.c = str5.l = 4;
+ str1.k = str2.j = str3.s = str4.d = str5.i = 5;
+ str1.m = str2.c = str4.e = 6;
+ str2.t = 7;
+ str2.u = 8;
+ str2.d = 9;
+ passing1 (str1, 4, 5, 6);
+ passing2 (str2, 4, 5, 6, 7, 8, 9);
+ passing3 (str3, 4, 5);
+ passing4 (str4, 4, 5, 6);
+ passing5 (str5, 4, 5);
+
+ u.c = 5;
+ passingU (u, 5);
+ u.s = 6;
+ passingU (u, 6);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c
new file mode 100644
index 00000000000..9e9678d7b02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_complex_returning.c
@@ -0,0 +1,83 @@
+/* This is a small test case for returning a complex number. Written by
+ Andreas Jaeger. */
+
+#include "defines.h"
+
+
+#define BUILD_F_COMPLEX(real, imag) \
+ ({ __complex__ float __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_D_COMPLEX(real, imag) \
+ ({ __complex__ double __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_LD_COMPLEX(real, imag) \
+ ({ __complex__ long double __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+__complex__ float
+aj_f_times2 (__complex__ float x)
+{
+ __complex__ float res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+__complex__ double
+aj_d_times2 (__complex__ double x)
+{
+ __complex__ double res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+__complex__ long double
+aj_ld_times2 (__complex__ long double x)
+{
+ __complex__ long double res;
+
+ __real__ res = (2.0 * __real__ x);
+ __imag__ res = (2.0 * __imag__ x);
+
+ return res;
+}
+
+int
+main (void)
+{
+#ifdef CHECK_COMPLEX
+ _Complex float fc, fd;
+ _Complex double dc, dd;
+ _Complex long double ldc, ldd;
+
+ fc = BUILD_LD_COMPLEX (2.0f, 3.0f);
+ fd = aj_f_times2 (fc);
+
+ assert (__real__ fd == 4.0f && __imag__ fd == 6.0f);
+
+ dc = BUILD_LD_COMPLEX (2.0, 3.0);
+ dd = aj_ld_times2 (dc);
+
+ assert (__real__ dd == 4.0 && __imag__ dd == 6.0);
+
+ ldc = BUILD_LD_COMPLEX (2.0L, 3.0L);
+ ldd = aj_ld_times2 (ldc);
+
+ assert (__real__ ldd == 4.0L && __imag__ ldd == 6.0L);
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c
new file mode 100644
index 00000000000..6bb24ccd75c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_floats.c
@@ -0,0 +1,608 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ float f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_float;
+
+struct
+{
+ double f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_double;
+
+struct
+{
+ ldouble f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23;
+} values_ldouble;
+
+void
+fun_check_float_passing_float8_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_float8_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_float16_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+ assert (values_float.f8 == f8);
+ assert (values_float.f9 == f9);
+ assert (values_float.f10 == f10);
+ assert (values_float.f11 == f11);
+ assert (values_float.f12 == f12);
+ assert (values_float.f13 == f13);
+ assert (values_float.f14 == f14);
+ assert (values_float.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_float16_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_float20_values (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED, float f16 ATTRIBUTE_UNUSED, float f17 ATTRIBUTE_UNUSED, float f18 ATTRIBUTE_UNUSED, float f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_float.f0 == f0);
+ assert (values_float.f1 == f1);
+ assert (values_float.f2 == f2);
+ assert (values_float.f3 == f3);
+ assert (values_float.f4 == f4);
+ assert (values_float.f5 == f5);
+ assert (values_float.f6 == f6);
+ assert (values_float.f7 == f7);
+ assert (values_float.f8 == f8);
+ assert (values_float.f9 == f9);
+ assert (values_float.f10 == f10);
+ assert (values_float.f11 == f11);
+ assert (values_float.f12 == f12);
+ assert (values_float.f13 == f13);
+ assert (values_float.f14 == f14);
+ assert (values_float.f15 == f15);
+ assert (values_float.f16 == f16);
+ assert (values_float.f17 == f17);
+ assert (values_float.f18 == f18);
+ assert (values_float.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_float20_regs (float f0 ATTRIBUTE_UNUSED, float f1 ATTRIBUTE_UNUSED, float f2 ATTRIBUTE_UNUSED, float f3 ATTRIBUTE_UNUSED, float f4 ATTRIBUTE_UNUSED, float f5 ATTRIBUTE_UNUSED, float f6 ATTRIBUTE_UNUSED, float f7 ATTRIBUTE_UNUSED, float f8 ATTRIBUTE_UNUSED, float f9 ATTRIBUTE_UNUSED, float f10 ATTRIBUTE_UNUSED, float f11 ATTRIBUTE_UNUSED, float f12 ATTRIBUTE_UNUSED, float f13 ATTRIBUTE_UNUSED, float f14 ATTRIBUTE_UNUSED, float f15 ATTRIBUTE_UNUSED, float f16 ATTRIBUTE_UNUSED, float f17 ATTRIBUTE_UNUSED, float f18 ATTRIBUTE_UNUSED, float f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_float_arguments;
+}
+
+void
+fun_check_float_passing_double8_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+
+}
+
+void
+fun_check_float_passing_double8_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_float_passing_double16_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+ assert (values_double.f8 == f8);
+ assert (values_double.f9 == f9);
+ assert (values_double.f10 == f10);
+ assert (values_double.f11 == f11);
+ assert (values_double.f12 == f12);
+ assert (values_double.f13 == f13);
+ assert (values_double.f14 == f14);
+ assert (values_double.f15 == f15);
+
+}
+
+void
+fun_check_float_passing_double16_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_float_passing_double20_values (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED, double f16 ATTRIBUTE_UNUSED, double f17 ATTRIBUTE_UNUSED, double f18 ATTRIBUTE_UNUSED, double f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_double.f0 == f0);
+ assert (values_double.f1 == f1);
+ assert (values_double.f2 == f2);
+ assert (values_double.f3 == f3);
+ assert (values_double.f4 == f4);
+ assert (values_double.f5 == f5);
+ assert (values_double.f6 == f6);
+ assert (values_double.f7 == f7);
+ assert (values_double.f8 == f8);
+ assert (values_double.f9 == f9);
+ assert (values_double.f10 == f10);
+ assert (values_double.f11 == f11);
+ assert (values_double.f12 == f12);
+ assert (values_double.f13 == f13);
+ assert (values_double.f14 == f14);
+ assert (values_double.f15 == f15);
+ assert (values_double.f16 == f16);
+ assert (values_double.f17 == f17);
+ assert (values_double.f18 == f18);
+ assert (values_double.f19 == f19);
+
+}
+
+void
+fun_check_float_passing_double20_regs (double f0 ATTRIBUTE_UNUSED, double f1 ATTRIBUTE_UNUSED, double f2 ATTRIBUTE_UNUSED, double f3 ATTRIBUTE_UNUSED, double f4 ATTRIBUTE_UNUSED, double f5 ATTRIBUTE_UNUSED, double f6 ATTRIBUTE_UNUSED, double f7 ATTRIBUTE_UNUSED, double f8 ATTRIBUTE_UNUSED, double f9 ATTRIBUTE_UNUSED, double f10 ATTRIBUTE_UNUSED, double f11 ATTRIBUTE_UNUSED, double f12 ATTRIBUTE_UNUSED, double f13 ATTRIBUTE_UNUSED, double f14 ATTRIBUTE_UNUSED, double f15 ATTRIBUTE_UNUSED, double f16 ATTRIBUTE_UNUSED, double f17 ATTRIBUTE_UNUSED, double f18 ATTRIBUTE_UNUSED, double f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_double_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble8_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+
+}
+
+void
+fun_check_x87_passing_ldouble8_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble16_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+ assert (values_ldouble.f8 == f8);
+ assert (values_ldouble.f9 == f9);
+ assert (values_ldouble.f10 == f10);
+ assert (values_ldouble.f11 == f11);
+ assert (values_ldouble.f12 == f12);
+ assert (values_ldouble.f13 == f13);
+ assert (values_ldouble.f14 == f14);
+ assert (values_ldouble.f15 == f15);
+
+}
+
+void
+fun_check_x87_passing_ldouble16_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+void
+fun_check_x87_passing_ldouble20_values (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED, ldouble f16 ATTRIBUTE_UNUSED, ldouble f17 ATTRIBUTE_UNUSED, ldouble f18 ATTRIBUTE_UNUSED, ldouble f19 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_ldouble.f0 == f0);
+ assert (values_ldouble.f1 == f1);
+ assert (values_ldouble.f2 == f2);
+ assert (values_ldouble.f3 == f3);
+ assert (values_ldouble.f4 == f4);
+ assert (values_ldouble.f5 == f5);
+ assert (values_ldouble.f6 == f6);
+ assert (values_ldouble.f7 == f7);
+ assert (values_ldouble.f8 == f8);
+ assert (values_ldouble.f9 == f9);
+ assert (values_ldouble.f10 == f10);
+ assert (values_ldouble.f11 == f11);
+ assert (values_ldouble.f12 == f12);
+ assert (values_ldouble.f13 == f13);
+ assert (values_ldouble.f14 == f14);
+ assert (values_ldouble.f15 == f15);
+ assert (values_ldouble.f16 == f16);
+ assert (values_ldouble.f17 == f17);
+ assert (values_ldouble.f18 == f18);
+ assert (values_ldouble.f19 == f19);
+
+}
+
+void
+fun_check_x87_passing_ldouble20_regs (ldouble f0 ATTRIBUTE_UNUSED, ldouble f1 ATTRIBUTE_UNUSED, ldouble f2 ATTRIBUTE_UNUSED, ldouble f3 ATTRIBUTE_UNUSED, ldouble f4 ATTRIBUTE_UNUSED, ldouble f5 ATTRIBUTE_UNUSED, ldouble f6 ATTRIBUTE_UNUSED, ldouble f7 ATTRIBUTE_UNUSED, ldouble f8 ATTRIBUTE_UNUSED, ldouble f9 ATTRIBUTE_UNUSED, ldouble f10 ATTRIBUTE_UNUSED, ldouble f11 ATTRIBUTE_UNUSED, ldouble f12 ATTRIBUTE_UNUSED, ldouble f13 ATTRIBUTE_UNUSED, ldouble f14 ATTRIBUTE_UNUSED, ldouble f15 ATTRIBUTE_UNUSED, ldouble f16 ATTRIBUTE_UNUSED, ldouble f17 ATTRIBUTE_UNUSED, ldouble f18 ATTRIBUTE_UNUSED, ldouble f19 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_ldouble_arguments;
+}
+
+#define def_check_float_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_float_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_float_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+#define def_check_x87_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
+
+#define def_check_x87_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15);
+
+#define def_check_x87_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19, _func1, _func2, TYPE) \
+ values_ ## TYPE .f0 = _f0; \
+ values_ ## TYPE .f1 = _f1; \
+ values_ ## TYPE .f2 = _f2; \
+ values_ ## TYPE .f3 = _f3; \
+ values_ ## TYPE .f4 = _f4; \
+ values_ ## TYPE .f5 = _f5; \
+ values_ ## TYPE .f6 = _f6; \
+ values_ ## TYPE .f7 = _f7; \
+ values_ ## TYPE .f8 = _f8; \
+ values_ ## TYPE .f9 = _f9; \
+ values_ ## TYPE .f10 = _f10; \
+ values_ ## TYPE .f11 = _f11; \
+ values_ ## TYPE .f12 = _f12; \
+ values_ ## TYPE .f13 = _f13; \
+ values_ ## TYPE .f14 = _f14; \
+ values_ ## TYPE .f15 = _f15; \
+ values_ ## TYPE .f16 = _f16; \
+ values_ ## TYPE .f17 = _f17; \
+ values_ ## TYPE .f18 = _f18; \
+ values_ ## TYPE .f19 = _f19; \
+ WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19); \
+ \
+ clear_int_registers; \
+ if (sizeof (TYPE) == 4) \
+ { \
+ u.f = _f0; \
+ iregs.I0 = u.i[0]; \
+ u.f = _f1; \
+ iregs.I1 = u.i[0]; \
+ u.f = _f2; \
+ iregs.I2 = u.i[0]; \
+ num_iregs = 3; \
+ } \
+ else \
+ { \
+ u.d = _f0; \
+ iregs.I0 = u.i[0]; \
+ iregs.I1 = u.i[1]; \
+ num_iregs = 2; \
+ } \
+ WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, _f18, _f19);
+
+void
+test_floats_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_float_passing_float8_values, fun_check_float_passing_float8_regs, float);
+
+ def_check_float_passing16(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, fun_check_float_passing_float16_values, fun_check_float_passing_float16_regs, float);
+}
+
+void
+test_too_many_floats ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_float_passing_float20_values, fun_check_float_passing_float20_regs, float);
+}
+
+void
+test_doubles_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_float_passing_double8_values, fun_check_float_passing_double8_regs, double);
+
+ def_check_float_passing16(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, fun_check_float_passing_double16_values, fun_check_float_passing_double16_regs, double);
+}
+
+void
+test_too_many_doubles ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_float_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_float_passing_double20_values, fun_check_float_passing_double20_regs, double);
+}
+
+void
+test_long_doubles_on_stack ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_x87_passing8(32, 33, 34, 35, 36, 37, 38, 39, fun_check_x87_passing_ldouble8_values, fun_check_x87_passing_ldouble8_regs, ldouble);
+}
+
+void
+test_too_many_long_doubles ()
+{
+ union
+ {
+ float f;
+ double d;
+ int i[2];
+ } u;
+ def_check_x87_passing20(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, fun_check_x87_passing_ldouble20_values, fun_check_x87_passing_ldouble20_regs, ldouble);
+}
+
+void
+test_float128s_on_stack ()
+{
+}
+
+void
+test_too_many_float128s ()
+{
+}
+
+
+int
+main (void)
+{
+ test_floats_on_stack ();
+ test_too_many_floats ();
+ test_doubles_on_stack ();
+ test_too_many_doubles ();
+ test_long_doubles_on_stack ();
+ test_too_many_long_doubles ();
+ test_float128s_on_stack ();
+ test_too_many_float128s ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c
new file mode 100644
index 00000000000..046e14037ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_integers.c
@@ -0,0 +1,182 @@
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
+} values_int;
+
+struct
+{
+ long i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23;
+} values_long;
+
+void
+fun_check_int_passing_int6_values (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_int.i0 == i0);
+ assert (values_int.i1 == i1);
+ assert (values_int.i2 == i2);
+ assert (values_int.i3 == i3);
+ assert (values_int.i4 == i4);
+ assert (values_int.i5 == i5);
+
+}
+
+void
+fun_check_int_passing_int6_regs (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_int_arguments;
+}
+
+void
+fun_check_int_passing_int12_values (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED, int i6 ATTRIBUTE_UNUSED, int i7 ATTRIBUTE_UNUSED, int i8 ATTRIBUTE_UNUSED, int i9 ATTRIBUTE_UNUSED, int i10 ATTRIBUTE_UNUSED, int i11 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_int.i0 == i0);
+ assert (values_int.i1 == i1);
+ assert (values_int.i2 == i2);
+ assert (values_int.i3 == i3);
+ assert (values_int.i4 == i4);
+ assert (values_int.i5 == i5);
+ assert (values_int.i6 == i6);
+ assert (values_int.i7 == i7);
+ assert (values_int.i8 == i8);
+ assert (values_int.i9 == i9);
+ assert (values_int.i10 == i10);
+ assert (values_int.i11 == i11);
+
+}
+
+void
+fun_check_int_passing_int12_regs (int i0 ATTRIBUTE_UNUSED, int i1 ATTRIBUTE_UNUSED, int i2 ATTRIBUTE_UNUSED, int i3 ATTRIBUTE_UNUSED, int i4 ATTRIBUTE_UNUSED, int i5 ATTRIBUTE_UNUSED, int i6 ATTRIBUTE_UNUSED, int i7 ATTRIBUTE_UNUSED, int i8 ATTRIBUTE_UNUSED, int i9 ATTRIBUTE_UNUSED, int i10 ATTRIBUTE_UNUSED, int i11 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_int_arguments;
+}
+
+void
+fun_check_int_passing_long6_values (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_long.i0 == i0);
+ assert (values_long.i1 == i1);
+ assert (values_long.i2 == i2);
+ assert (values_long.i3 == i3);
+ assert (values_long.i4 == i4);
+ assert (values_long.i5 == i5);
+
+}
+
+void
+fun_check_int_passing_long6_regs (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_long_arguments;
+}
+
+void
+fun_check_int_passing_long12_values (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED, long i6 ATTRIBUTE_UNUSED, long i7 ATTRIBUTE_UNUSED, long i8 ATTRIBUTE_UNUSED, long i9 ATTRIBUTE_UNUSED, long i10 ATTRIBUTE_UNUSED, long i11 ATTRIBUTE_UNUSED)
+{
+ /* Check argument values. */
+ assert (values_long.i0 == i0);
+ assert (values_long.i1 == i1);
+ assert (values_long.i2 == i2);
+ assert (values_long.i3 == i3);
+ assert (values_long.i4 == i4);
+ assert (values_long.i5 == i5);
+ assert (values_long.i6 == i6);
+ assert (values_long.i7 == i7);
+ assert (values_long.i8 == i8);
+ assert (values_long.i9 == i9);
+ assert (values_long.i10 == i10);
+ assert (values_long.i11 == i11);
+
+}
+
+void
+fun_check_int_passing_long12_regs (long i0 ATTRIBUTE_UNUSED, long i1 ATTRIBUTE_UNUSED, long i2 ATTRIBUTE_UNUSED, long i3 ATTRIBUTE_UNUSED, long i4 ATTRIBUTE_UNUSED, long i5 ATTRIBUTE_UNUSED, long i6 ATTRIBUTE_UNUSED, long i7 ATTRIBUTE_UNUSED, long i8 ATTRIBUTE_UNUSED, long i9 ATTRIBUTE_UNUSED, long i10 ATTRIBUTE_UNUSED, long i11 ATTRIBUTE_UNUSED)
+{
+ /* Check register contents. */
+ check_long_arguments;
+}
+
+#define def_check_int_passing6(_i0, _i1, _i2, _i3, _i4, _i5, _func1, _func2, TYPE) \
+ values_ ## TYPE .i0 = _i0; \
+ values_ ## TYPE .i1 = _i1; \
+ values_ ## TYPE .i2 = _i2; \
+ values_ ## TYPE .i3 = _i3; \
+ values_ ## TYPE .i4 = _i4; \
+ values_ ## TYPE .i5 = _i5; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5); \
+ \
+ clear_int_registers; \
+ iregs.I0 = _i0; \
+ iregs.I1 = _i1; \
+ iregs.I2 = _i2; \
+ num_iregs = 3; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5);
+
+#define def_check_int_passing12(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11, _func1, _func2, TYPE) \
+ values_ ## TYPE .i0 = _i0; \
+ values_ ## TYPE .i1 = _i1; \
+ values_ ## TYPE .i2 = _i2; \
+ values_ ## TYPE .i3 = _i3; \
+ values_ ## TYPE .i4 = _i4; \
+ values_ ## TYPE .i5 = _i5; \
+ values_ ## TYPE .i6 = _i6; \
+ values_ ## TYPE .i7 = _i7; \
+ values_ ## TYPE .i8 = _i8; \
+ values_ ## TYPE .i9 = _i9; \
+ values_ ## TYPE .i10 = _i10; \
+ values_ ## TYPE .i11 = _i11; \
+ WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11); \
+ \
+ clear_int_registers; \
+ iregs.I0 = _i0; \
+ iregs.I1 = _i1; \
+ iregs.I2 = _i2; \
+ num_iregs = 3; \
+ WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10, _i11);
+
+void
+test_ints_on_stack ()
+{
+ def_check_int_passing6(32, 33, 34, 35, 36, 37, fun_check_int_passing_int6_values, fun_check_int_passing_int6_regs, int);
+}
+
+void
+test_too_many_ints ()
+{
+ def_check_int_passing12(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, fun_check_int_passing_int12_values, fun_check_int_passing_int12_regs, int);
+}
+
+void
+test_longs_on_stack ()
+{
+ def_check_int_passing6(32, 33, 34, 35, 36, 37, fun_check_int_passing_long6_values, fun_check_int_passing_long6_regs, long);
+}
+
+void
+test_too_many_longs ()
+{
+ def_check_int_passing12(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, fun_check_int_passing_long12_values, fun_check_int_passing_long12_regs, long);
+}
+
+int
+main (void)
+{
+ test_ints_on_stack ();
+ test_too_many_ints ();
+ test_longs_on_stack ();
+ test_too_many_longs ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c
new file mode 100644
index 00000000000..1660a4d430b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs.c
@@ -0,0 +1,237 @@
+/* This tests passing of structs. */
+
+#include "defines.h"
+#include "args.h"
+#include <complex.h>
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct long_struct
+{
+ long l;
+};
+
+struct longlong2_struct
+{
+ long long ll1, ll2;
+};
+
+struct longlong3_struct
+{
+ long long ll1, ll2, ll3;
+};
+
+/* Check that the struct is passed as the individual members in iregs. */
+void
+check_struct_passing1 (struct int_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing2 (struct long_struct ls ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing3 (struct longlong2_struct ls ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing4 (struct longlong3_struct ls ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.ll1 == esp+4);
+ assert ((unsigned long)&ls.ll2 == esp+12);
+ assert ((unsigned long)&ls.ll3 == esp+20);
+}
+
+struct flex1_struct
+{
+ long i;
+ long flex[];
+};
+
+struct flex2_struct
+{
+ long i;
+ long flex[0];
+};
+
+void
+check_struct_passing7 (struct flex1_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_struct_passing8 (struct flex2_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct complex1_struct
+{
+ __complex__ float x;
+};
+
+struct complex1a_struct
+{
+ long l;
+ union
+ {
+ float f;
+ int i;
+ } u;
+};
+
+void
+check_struct_passing9 (struct complex1_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct long3_struct
+{
+ long l1, l2, l3;
+};
+
+void
+check_struct_passing10 (struct long3_struct ls ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.l1 == esp+4);
+ assert ((unsigned long)&ls.l2 == esp+8);
+ assert ((unsigned long)&ls.l3 == esp+12);
+}
+
+struct char3_struct
+{
+ char c1, c2, c3;
+};
+
+void
+check_struct_passing11 (struct char3_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+struct char7_struct
+{
+ char c1, c2, c3, c4, c5, c6, c7;
+};
+
+void
+check_struct_passing12 (struct char7_struct is ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+static struct flex1_struct f1s = { 60, { } };
+static struct flex2_struct f2s = { 61, { } };
+
+int
+main (void)
+{
+ struct int_struct is = { 48 };
+ struct long_struct ls = { 49 };
+#ifdef CHECK_LARGER_STRUCTS
+ struct longlong2_struct ll2s = { 50, 51 };
+ struct longlong3_struct ll3s = { 52, 53, 54 };
+ struct long3_struct l3s = { 60, 61, 62 };
+#endif
+ struct complex1_struct c1s = { ( -13.4 + 3.5*I ) };
+ union
+ {
+ struct complex1_struct c;
+ struct complex1a_struct u;
+ } c1u;
+ struct char3_struct c3 = { 0x12, 0x34, 0x56 };
+ union
+ {
+ struct char3_struct c;
+ int i;
+ } c3u;
+ struct char7_struct c7 = { 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56 };
+ union
+ {
+ struct char7_struct c;
+ struct
+ {
+ int i0, i1;
+ } i;
+ } c7u;
+
+ clear_struct_registers;
+ iregs.I0 = is.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing1)(is);
+
+ clear_struct_registers;
+ iregs.I0 = ls.l;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing2)(ls);
+
+#ifdef CHECK_LARGER_STRUCTS
+ clear_struct_registers;
+ num_iregs = 0;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing3)(ll2s);
+ WRAP_CALL (check_struct_passing4)(ll3s);
+ WRAP_CALL (check_struct_passing10)(l3s);
+#endif
+
+ clear_struct_registers;
+ iregs.I0 = f1s.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing7)(f1s);
+
+ clear_struct_registers;
+ iregs.I0 = f2s.i;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing8)(f2s);
+
+ clear_struct_registers;
+ c1u.c = c1s;
+ iregs.I0 = c1u.u.l;
+ iregs.I1 = c1u.u.u.i;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing9)(c1s);
+
+ clear_struct_registers;
+ c3u.c = c3;
+ iregs.I0 = c3u.i;
+ iregbits.I0 = 0xffffff;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing11)(c3);
+
+ clear_struct_registers;
+ c7u.c = c7;
+ iregs.I0 = c7u.i.i0;
+ iregs.I1 = c7u.i.i1;
+ iregbits.I0 = 0xffffffff;
+ iregbits.I1 = 0xffffff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_struct_passing12)(c7);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c
new file mode 100644
index 00000000000..ff6354cd6fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_structs_and_unions.c
@@ -0,0 +1,97 @@
+/* This tests passing of structs. Only integers are tested. */
+
+#include "defines.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct longlong_struct
+{
+ long long ll;
+};
+
+struct long2_struct
+{
+ long long ll1, ll2;
+};
+
+struct long3_struct
+{
+ long l1, l2, l3;
+};
+
+union un1
+{
+ char c;
+ int i;
+};
+
+union un2
+{
+ char c1;
+ long l;
+ char c2;
+};
+
+union un3
+{
+ struct int_struct is;
+ struct longlong_struct ls;
+ union un1 un;
+};
+
+
+void
+check_mixed_passing1 (char c1 ATTRIBUTE_UNUSED, struct int_struct is ATTRIBUTE_UNUSED, char c2 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_mixed_passing2 (char c1 ATTRIBUTE_UNUSED, struct long3_struct ls ATTRIBUTE_UNUSED, char c2 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&ls.l1 == esp+4);
+ assert ((unsigned long)&ls.l2 == esp+8);
+ assert ((unsigned long)&ls.l3 == esp+12);
+}
+
+int
+main (void)
+{
+ struct int_struct is = { 64 };
+#ifdef CHECK_LARGER_STRUCTS
+ struct long3_struct l3s = { 65, 66, 67 };
+#endif
+
+ clear_struct_registers;
+ iregs.I0 = 8;
+ iregs.I1 = 64;
+ iregs.I2 = 9;
+ num_iregs = 3;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_mixed_passing1)(8, is, 9);
+
+#ifdef CHECK_LARGER_STRUCTS
+ clear_struct_registers;
+ iregs.I0 = 10;
+ iregbits.I0 = 0xff;
+ iregs.I1 = 11;
+ iregbits.I1 = 0xff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ WRAP_CALL (check_mixed_passing2)(10, l3s, 11);
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c
new file mode 100644
index 00000000000..534fc8505ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_passing_unions.c
@@ -0,0 +1,221 @@
+/* This tests passing of structs. */
+
+#include "defines.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+struct int_struct
+{
+ int i;
+};
+
+struct long_struct
+{
+ long l;
+};
+
+union un1
+{
+ char c;
+ int i;
+};
+
+union un2
+{
+ char c1;
+ long l;
+ char c2;
+};
+
+union un3
+{
+ struct int_struct is;
+ struct long_struct ls;
+ union un1 un;
+};
+
+
+void
+check_union_passing1(union un1 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing2(union un2 u1 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing3(union un3 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+#define check_union_passing1 WRAP_CALL(check_union_passing1)
+#define check_union_passing2 WRAP_CALL(check_union_passing2)
+#define check_union_passing3 WRAP_CALL(check_union_passing3)
+
+union un4
+{
+ int i;
+ float f;
+};
+
+union un5
+{
+ long long ll;
+ double d;
+};
+
+void
+check_union_passing4(union un4 u1 ATTRIBUTE_UNUSED,
+ union un4 u2 ATTRIBUTE_UNUSED,
+ union un4 u3 ATTRIBUTE_UNUSED,
+ union un4 u4 ATTRIBUTE_UNUSED,
+ union un4 u5 ATTRIBUTE_UNUSED,
+ union un4 u6 ATTRIBUTE_UNUSED,
+ union un4 u7 ATTRIBUTE_UNUSED,
+ union un4 u8 ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+void
+check_union_passing5(union un5 u ATTRIBUTE_UNUSED)
+{
+ check_int_arguments;
+}
+
+#define check_union_passing4 WRAP_CALL(check_union_passing4)
+#define check_union_passing5 WRAP_CALL(check_union_passing5)
+
+union un6
+{
+ __float128 f128;
+ int i;
+};
+
+
+void
+check_union_passing6(union un6 u ATTRIBUTE_UNUSED)
+{
+ /* Check the passing on the stack by comparing the address of the
+ stack elements to the expected place on the stack. */
+ assert ((unsigned long)&u.f128 == esp+4);
+ assert ((unsigned long)&u.i == esp+4);
+}
+
+#define check_union_passing6 WRAP_CALL(check_union_passing6)
+
+int
+main (void)
+{
+ union un1 u1;
+#ifdef CHECK_LARGER_UNION_PASSING
+ union un2 u2;
+ union un3 u3;
+ struct int_struct is;
+ struct long_struct ls;
+#endif /* CHECK_LARGER_UNION_PASSING */
+ union un4 u4[8];
+ union un5 u5 = { { 48.394, 39.3, -397.9, 3484.9 } };
+ int i;
+ union un6 u6;
+
+ /* Check a union with char, int. */
+ clear_struct_registers;
+ u1.i = 0; /* clear the struct to not have high bits left */
+ u1.c = 32;
+ iregs.I0 = 32;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing1(u1);
+ u1.i = 0; /* clear the struct to not have high bits left */
+ u1.i = 33;
+ iregs.I0 = 33;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing1(u1);
+
+ /* Check a union with char, long, char. */
+#ifdef CHECK_LARGER_UNION_PASSING
+ clear_struct_registers;
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.c1 = 34;
+ iregs.I0 = 34;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.l = 35;
+ iregs.I0 = 35;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+ u2.l = 0; /* clear the struct to not have high bits left */
+ u2.c2 = 36;
+ iregs.I0 = 36;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing2(u2);
+
+ /* check a union containing two structs and a union. */
+ clear_struct_registers;
+ is.i = 37;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.is = is;
+ iregs.I0 = 37;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ ls.l = 38;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.ls = ls;
+ iregs.I0 = 38;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ u1.c = 39;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.un = u1;
+ iregs.I0 = 39;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+ u1.i = 40;
+ u3.ls.l = 0; /* clear the struct to not have high bits left */
+ u3.un = u1;
+ iregs.I0 = 40;
+ num_iregs = 1;
+ clear_int_hardware_registers;
+ check_union_passing3(u3);
+#endif /* CHECK_LARGER_UNION_PASSING */
+
+ clear_struct_registers;
+ for (i = 0; i < 8; i++)
+ u4[i].f = 32 + i;
+ iregs.I0 = u4[0].i;
+ iregs.I1 = u4[1].i;
+ iregs.I2 = u4[2].i;
+ num_iregs = 3;
+ clear_int_hardware_registers;
+ check_union_passing4(u4[0], u4[1], u4[2], u4[3],
+ u4[4], u4[5], u4[6], u4[7]);
+
+ clear_struct_registers;
+ iregs.I0 = u5.ll & 0xffffffff;
+ iregs.I1 = (u5.ll >> 32) & 0xffffffff;
+ num_iregs = 2;
+ clear_int_hardware_registers;
+ check_union_passing5(u5);
+
+ u6.i = 2;
+ check_union_passing6(u6);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c b/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c
new file mode 100644
index 00000000000..49a6b1f0a6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_struct_returning.c
@@ -0,0 +1,362 @@
+/* This tests returning of structures. */
+
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregbits = { ~0, ~0, ~0, ~0, ~0, ~0 };
+struct IntegerRegisters iregs;
+unsigned int num_iregs;
+
+int current_test;
+int num_failed = 0;
+
+typedef enum {
+ EAX = 0,
+ EAX_EDX,
+ LONG_LONG,
+ FLOAT,
+ DOUBLE,
+ FLOAT_FLOAT,
+ EAX_FLOAT,
+ FLOAT_EDX,
+ MEM
+} Type;
+
+/* Structures which should be returned in EAX/LONG_LONG/EAX_EDX. */
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; iamcu_memset (&s, 0, sizeof(s)); B; return s; }
+
+D(1,char m1, EAX, s.m1=42)
+D(2,short m1, EAX, s.m1=42)
+D(3,int m1, EAX, s.m1=42)
+D(4,char m1[3], EAX, s.m1[0]=42)
+D(5,char m1[4], EAX, s.m1[0]=42)
+D(6,char m1;char m2; char m3, EAX, s.m1=42)
+D(7,char m1;short m2, EAX, s.m1=42)
+
+D(30,long long m1, LONG_LONG, s.m1=0xadadbeefadadbeefLL)
+
+D(50,short m1;int m2, EAX_EDX, s.m1=42; s.m2=43)
+D(51,char m1;int m2, EAX_EDX, s.m1=42; s.m2=43)
+D(52,char m1[5], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(53,char m1[6], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(54,char m1[7], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(55,char m1[8], EAX_EDX, s.m1[0]=42; s.m1[4]=43)
+D(56,char m1;short m2[2], EAX_EDX, s.m1=42; s.m2[1]=43)
+D(57,short m1[4], EAX_EDX, s.m1[0]=42; s.m1[2]=43)
+D(58,int m1[2], EAX_EDX, s.m1[0]=42; s.m1[1]=43)
+D(59,int m1;char m2, EAX_EDX, s.m1=42; s.m2=43)
+D(60,int m1;short m2, EAX_EDX, s.m1=42; s.m2=43)
+D(61,int m1;short m2; char m3, EAX_EDX, s.m1=42; s.m2=43)
+D(62,int m1;char m2; short m3, EAX_EDX, s.m1=42; s.m2=43)
+
+/* Packed members. */
+D(100,short m1[1];int m2 PACKED, EAX_EDX, s.m1[0]=42; s.m2=43)
+D(101,char m1; short m2 PACKED; char m3, EAX_EDX, s.m1=42; s.m3=43)
+
+/* Structures which should be returned in FLOAT/DOUBLE. */
+#undef D
+#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; iamcu_memset (&s, 0, sizeof(s)); B; return s; }
+
+D(200,float f, FLOAT, s.f=42)
+D(201,double d, DOUBLE, s.d=42)
+
+D(300,float m;char m2, FLOAT_EDX, s.m=42; s.m2=43)
+D(301,float m;short m2, FLOAT_EDX, s.m=42; s.m2=43)
+D(302,float m;int m2, FLOAT_EDX, s.m=42; s.m2=43)
+
+D(400,char m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+D(401,short m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+D(402,int m1; float m2, EAX_FLOAT, s.m1=42; s.m2=43)
+
+D(500,float m;float m2, FLOAT_FLOAT, s.m=42; s.m2=43)
+D(501,float f[2], FLOAT, s.f[0]=42; s.f[1]=43)
+
+/* Structures which should be returned in MEM. */
+void *struct_addr;
+#undef D
+#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
+struct S_ ## I f_ ## I (void) { union {unsigned char c; struct S_ ## I s;} u; iamcu_memset (&u.s, 0, sizeof(u.s)); u.c = 42; return u.s; }
+
+/* Too large. */
+D(600,char m1[17])
+D(601,short m1[9])
+D(602,int m1[5])
+D(603,long m1[3])
+D(604,short m1[8];char c)
+D(605,char m1[1];int i[4])
+D(606,float m1[5])
+D(607,double m1[3])
+D(608,char m1[1];float f[4])
+D(609,char m1[1];double d[2])
+D(610,__complex long double m1[1])
+
+/* Too large due to padding. */
+D(611,char m1[1]; int i; char c2)
+
+/* Special tests. */
+#undef D
+#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
+struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
+D(700,float f[4], s.f[0] = s.f[1] = s.f[2] = s.f[3] = 42)
+
+void
+check_eax (void)
+{
+ switch (current_test)
+ {
+ case 1:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ eax &= 0xff;
+ break;
+ case 2:
+ eax &= 0xffff;
+ break;
+ case 3:
+ eax &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ if (eax != 42)
+ num_failed++;
+}
+
+void
+check_eax_edx (void)
+{
+ unsigned long long ll = eax | ((unsigned long long) edx) << 32;
+ switch (current_test)
+ {
+ case 50:
+ eax &= 0xffff;
+ break;
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ edx &= 0xff;
+ case 51:
+ eax &= 0xff;
+ break;
+ case 56:
+ eax &= 0xff;
+ edx &= 0xffff;
+ break;
+ case 57:
+ eax &= 0xffff;
+ edx &= 0xffff;
+ break;
+ case 58:
+ break;
+ case 59:
+ case 62:
+ edx &= 0xff;
+ break;
+ case 60:
+ case 61:
+ edx &= 0xffff;
+ break;
+ case 100:
+ eax &= 0xffff;
+ edx = (ll >> 16) & 0xffffffff;
+ break;
+ case 101:
+ edx = (eax >> 24) & 0xff;
+ eax &= 0xff;
+ break;
+ default:
+ abort ();
+ }
+ if (eax != 42 || edx != 43)
+ num_failed++;
+}
+
+void
+check_float_edx (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } ueax;
+ switch (current_test)
+ {
+ case 300:
+ edx &= 0xff;
+ break;
+ case 301:
+ edx &= 0xffff;
+ break;
+ case 302:
+ edx &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ ueax.l = eax;
+ if (ueax.f != 42 || edx != 43)
+ num_failed++;
+}
+
+void
+check_eax_float (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } uedx;
+ switch (current_test)
+ {
+ case 400:
+ eax &= 0xff;
+ break;
+ case 401:
+ eax &= 0xffff;
+ break;
+ case 402:
+ eax &= 0xffff;
+ break;
+ default:
+ abort ();
+ }
+ uedx.l = edx;
+ if (eax != 42 || uedx.f != 43)
+ num_failed++;
+}
+
+void
+check_float_float (void)
+{
+ union
+ {
+ unsigned long l;
+ float f;
+ } ueax, uedx;
+ switch (current_test)
+ {
+ case 500:
+ case 501:
+ break;
+ default:
+ abort ();
+ }
+ ueax.l = eax;
+ uedx.l = edx;
+ if (ueax.f != 42 || uedx.f != 43)
+ num_failed++;
+}
+
+void
+check_all (Type class, unsigned long size)
+{
+ union
+ {
+ struct
+ {
+ unsigned long eax;
+ unsigned long edx;
+ } eax_edx;
+ unsigned long long ll;
+ float f;
+ double d;
+ } u;
+
+ switch (class)
+ {
+ case EAX:
+ check_eax ();
+ break;
+ case LONG_LONG:
+ if (0xadadbeefL != eax || 0xadadbeefL != edx)
+ num_failed++;
+ break;
+ case EAX_EDX:
+ check_eax_edx ();
+ break;
+ case FLOAT:
+ u.eax_edx.eax = eax;
+ if (u.f != 42)
+ num_failed++;
+ break;
+ case DOUBLE:
+ u.eax_edx.eax = eax;
+ u.eax_edx.edx = edx;
+ if (u.d != 42)
+ num_failed++;
+ break;
+ case FLOAT_EDX:
+ check_float_edx ();
+ break;
+ case FLOAT_FLOAT:
+ check_float_float ();
+ break;
+ case EAX_FLOAT:
+ check_eax_float ();
+ break;
+ case MEM:
+ /* sret_eax contains a slot whose address is given to the f_*
+ functions. The slot may be a temporary one on stack. When
+ this function is called, hopefully this slot hasn't be
+ overriden. */
+ if (sret_eax != eax)
+ num_failed++;
+ else if (current_test < 700)
+ {
+ if (*(unsigned char*)sret_eax != 42
+ || *(unsigned char*)struct_addr != 42)
+ num_failed++;
+ }
+ else
+ {
+ if (*(float *)sret_eax != 42
+ || *(float *)struct_addr != 42)
+ num_failed++;
+ }
+ break;
+ }
+}
+
+#undef D
+#define D(I) { static struct S_ ## I s; current_test = I; struct_addr = (void*)&s; \
+ clear_non_sret_int_registers; \
+ s = WRAP_RET(f_ ## I) (); \
+ check_all(class_ ## I, sizeof(s)); \
+}
+
+int
+main (void)
+{
+ D(1) D(2) D(3) D(4) D(5) D(6) D(7)
+
+ D(30)
+
+ D(50) D(51) D(52) D(53) D(54) D(55) D(56) D(57) D(58) D(59)
+ D(60) D(61) D(62)
+
+ D(100) D(101)
+
+ D(200) D(201)
+
+ D(300) D(301) D(302)
+
+ D(400) D(401) D(402)
+
+ D(500) D(501)
+
+ D(600) D(601) D(602) D(603) D(604) D(605) D(606) D(607) D(608) D(609)
+ D(610) D(611)
+
+ D(700)
+
+ if (num_failed)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c b/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c
new file mode 100644
index 00000000000..124bef17c62
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/iamcu/test_varargs.c
@@ -0,0 +1,101 @@
+/* Test variable number of arguments passed to functions. */
+
+#include <stdarg.h>
+#include "defines.h"
+
+
+#define ARG_INT 1
+#define ARG_DOUBLE 2
+#define ARG_POINTER 3
+
+union types
+{
+ int ivalue;
+ double dvalue;
+ void *pvalue;
+};
+
+struct arg
+{
+ int type;
+ union types value;
+};
+
+struct arg *arglist;
+
+/* This tests the argumentlist to see if it matches the format string which
+ is printf-like. Nothing will be printed of course. It can handle ints,
+ doubles and void pointers. The given value will be tested against the
+ values given in arglist.
+ This test only assures that the variable argument passing is working.
+ No attempt is made to see if argument passing is done the right way. */
+void
+__attribute__ ((noinline))
+noprintf (char *format, ...)
+{
+ va_list va_arglist;
+ char *c;
+
+ int ivalue;
+ double dvalue;
+ void *pvalue;
+ struct arg *argp = arglist;
+
+ va_start (va_arglist, format);
+ for (c = format; *c; c++)
+ if (*c == '%')
+ {
+ switch (*++c)
+ {
+ case 'd':
+ assert (argp->type == ARG_INT);
+ ivalue = va_arg (va_arglist, int);
+ assert (argp->value.ivalue == ivalue);
+ break;
+ case 'f':
+ assert (argp->type == ARG_DOUBLE);
+ dvalue = va_arg (va_arglist, double);
+ assert (argp->value.dvalue == dvalue);
+ break;
+ case 'p':
+ assert (argp->type == ARG_POINTER);
+ pvalue = va_arg (va_arglist, void *);
+ assert (argp->value.pvalue == pvalue);
+ break;
+ default:
+ abort ();
+ }
+
+ argp++;
+ }
+}
+
+extern void iamcu_noprintf (char *, ...);
+
+int
+main (void)
+{
+#ifdef CHECK_VARARGS
+ float f = 258.0;
+ struct arg al[5];
+
+ al[0].type = ARG_INT;
+ al[0].value.ivalue = 256;
+ al[1].type = ARG_DOUBLE;
+ al[1].value.dvalue = 257.0;
+ al[2].type = ARG_POINTER;
+ al[2].value.pvalue = al;
+ al[3].type = ARG_DOUBLE;
+ al[3].value.dvalue = f;
+ al[4].type = ARG_INT;
+ al[4].value.ivalue = 259;
+
+ arglist = al;
+ noprintf("%d%f%p%f%d", 256, 257.0, al, f, 259);
+
+ iamcu_noprintf ((char *) 0xabadbeef, 256, 257.0,
+ (void *) 0xbbadbeef, f, 259);
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr66691.c b/gcc/testsuite/gcc.target/i386/pr66691.c
new file mode 100644
index 00000000000..407aba908bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66691.c
@@ -0,0 +1,64 @@
+/* PR target/66691 */
+/* { dg-do compile } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O3 -g -mtune=generic -march=i686" } */
+
+unsigned int a;
+int b[2], c, d, e, f, g, h, i, k[8], l, m, s, t, w;
+static int j;
+
+void
+fn1 (long long p)
+{
+ int t = p;
+ c = c ^ b[c ^ (t & 1)];
+}
+
+static void
+fn2 (long long p)
+{
+ c = c ^ b[1 ^ (d & 1)];
+ fn1 (p >> 1 & 1);
+ fn1 (p >> 2);
+}
+
+static void
+fn3 ()
+{
+ unsigned char p;
+ f = g = 0;
+ for (h = 0; h < 6; h++)
+ {
+ for (s = 0; s < 7; s++)
+ if (k[s+1])
+ g = 0;
+ else
+ for (j = 0; j < 2; j++)
+ ;
+ t = j > 2 ? 0 : 1 >> j;
+ }
+ if (l)
+ {
+ short q[2];
+ q[0] = q[1] = 0;
+ if (m)
+ for (i = 0; i < 2; i++)
+ {
+ unsigned char r = q[i];
+ p = f ? r % f : r;
+ e = ((p > 0) <= (q[i] ^ 1)) + a;
+ if (k[1])
+ for (e = 0; e != 18; ++e)
+ k[0] = 0;
+ }
+ }
+}
+
+int
+main ()
+{
+ fn3 ();
+ fn2 (w);
+ fn2 (j);
+ return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/wunused-parameter.f90 b/gcc/testsuite/gfortran.dg/wunused-parameter.f90
new file mode 100644
index 00000000000..df39af8aa57
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/wunused-parameter.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+! { dg-options "-Wunused-parameter" }
+! PR66605
+MODULE test
+ IMPLICIT NONE
+ INTEGER, PARAMETER :: wp = KIND(1.0D0)
+CONTAINS
+SUBROUTINE sub (neq, time, y, dydt)
+ IMPLICIT NONE
+ INTEGER :: neq
+ REAL(WP) :: time, y(neq), dydt(neq)
+
+ dydt(1) = 1.0 / y(1)
+END SUBROUTINE sub
+END MODULE
diff --git a/gcc/testsuite/gnat.dg/lto17.adb b/gcc/testsuite/gnat.dg/lto17.adb
new file mode 100644
index 00000000000..af42e8d85d8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/lto17.adb
@@ -0,0 +1,12 @@
+-- { dg-do compile }
+-- { dg-options "-flto" }
+-- { dg-require-effective-target lto }
+
+package body Lto17 is
+
+ function To_Chunk_List(C : Chunk) return Chunk_List is
+ begin
+ return new Chunk_List_Element'(C.Size, C, null);
+ end;
+
+end Lto17;
diff --git a/gcc/testsuite/gnat.dg/lto17.ads b/gcc/testsuite/gnat.dg/lto17.ads
new file mode 100644
index 00000000000..19b8a9c7c16
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/lto17.ads
@@ -0,0 +1,20 @@
+package Lto17 is
+
+ type Chunk_List_Element;
+ type Chunk_List is access Chunk_List_Element;
+
+ type Arr is array (Natural range <>) of Integer;
+
+ type Chunk(Size : Natural) is record
+ Data : Arr(1 .. Size);
+ Where : Natural;
+ end record;
+
+ type Chunk_List_Element(Size : Natural) is record
+ Chnk : Chunk(Size);
+ Link : Chunk_List;
+ end record;
+
+ function To_Chunk_List(C : Chunk) return Chunk_List;
+
+end Lto17;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 389e1c63ff0..36a616018d5 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -95,6 +95,9 @@
#undef create_code
#undef verify_code
+/* test-extra-options.c: We don't use this one, since the extra options
+ affect the whole context. */
+
/* test-factorial.c */
#define create_code create_code_factorial
#define verify_code verify_code_factorial
@@ -172,6 +175,13 @@
#undef create_code
#undef verify_code
+/* test-switch.c */
+#define create_code create_code_switch
+#define verify_code verify_code_switch
+#include "test-switch.c"
+#undef create_code
+#undef verify_code
+
/* test-types.c */
#define create_code create_code_types
#define verify_code verify_code_types
@@ -186,6 +196,10 @@
#undef create_code
#undef verify_code
+/* test-validly-unreachable-block.c: We don't use this one, since the use
+ of gcc_jit_context_set_bool_allow_unreachable_blocks affects the whole
+ context. */
+
/* test-volatile.c */
#define create_code create_code_volatile
#define verify_code verify_code_volatile
@@ -274,6 +288,9 @@ const struct testcase testcases[] = {
{"sum_of_squares",
create_code_sum_of_squares,
verify_code_sum_of_squares},
+ {"switch",
+ create_code_switch,
+ verify_code_switch},
{"types",
create_code_types,
verify_code_types},
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-NULL-case.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-NULL-case.c
new file mode 100644
index 00000000000..07a98480693
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-NULL-case.c
@@ -0,0 +1,66 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ {
+ switch (x)
+ {
+ case x:
+ return 3;
+
+ default:
+ return 10;
+ }
+ }
+ and verify that we get a sane error about the non-const
+ case.
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *return_type = t_int;
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (ctxt, NULL, t_int, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ 1, params, 0);
+
+ gcc_jit_block *b_initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block *b_default =
+ gcc_jit_function_new_block (func, "default");
+
+ gcc_jit_case *cases[1] = {
+ NULL
+ };
+
+ gcc_jit_block_end_with_switch (
+ b_initial, NULL,
+ gcc_jit_param_as_rvalue (x),
+ b_default,
+ 1,
+ cases);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_block_end_with_switch: NULL case 0");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-mismatching-case-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-mismatching-case-type.c
new file mode 100644
index 00000000000..cc907cea1d8
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-mismatching-case-type.c
@@ -0,0 +1,83 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ {
+ switch (x)
+ {
+ case (long long)0 ... (long long)5:
+ return 3;
+ default:
+ return 10;
+ }
+ }
+ and verify that the floating-point case is an error.
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *t_long_long =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG_LONG);
+ gcc_jit_type *return_type = t_int;
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (ctxt, NULL, t_int, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ 1, params, 0);
+
+ gcc_jit_block *b_initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block *b_default =
+ gcc_jit_function_new_block (func, "default");
+ gcc_jit_block *b_case_0 =
+ gcc_jit_function_new_block (func, "case_0");
+
+ /* Note the erroneous use of "t_float" here. */
+ gcc_jit_case *cases[1] = {
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_long_long, 0),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_long_long, 5),
+ b_case_0)
+ };
+
+ gcc_jit_block_end_with_switch (
+ b_initial, NULL,
+ gcc_jit_param_as_rvalue (x),
+ b_default,
+ 1,
+ cases);
+
+ gcc_jit_block_end_with_return (
+ b_case_0, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3));
+ gcc_jit_block_end_with_return (
+ b_default, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_block_end_with_switch:"
+ " mismatching types between case and expression:"
+ " cases[0]->min_value: (long long)0 (type: long long)"
+ " expr: x (type: int)");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-overlapping-ranges.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-overlapping-ranges.c
new file mode 100644
index 00000000000..40655c244a0
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_block_end_with_switch-overlapping-ranges.c
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ {
+ switch (x)
+ {
+ case 0 ... 5:
+ return 3;
+
+ case 5 ... 10:
+ return 4;
+
+ default:
+ return 10;
+ }
+ }
+ and verify that we get an error about the overlapping
+ ranges.
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *return_type = t_int;
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (ctxt, NULL, t_int, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ 1, params, 0);
+
+ gcc_jit_block *b_initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block *b_default =
+ gcc_jit_function_new_block (func, "default");
+ gcc_jit_block *b_case_0_5 =
+ gcc_jit_function_new_block (func, "case_0_5");
+ gcc_jit_block *b_case_5_10 =
+ gcc_jit_function_new_block (func, "case_5_10");
+
+ gcc_jit_case *cases[2] = {
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 0),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 5),
+ b_case_0_5),
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 5),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10),
+ b_case_5_10)
+ };
+
+ gcc_jit_block_end_with_switch (
+ b_initial, NULL,
+ gcc_jit_param_as_rvalue (x),
+ b_default,
+ 2,
+ cases);
+
+ gcc_jit_block_end_with_return (
+ b_case_0_5, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3));
+ gcc_jit_block_end_with_return (
+ b_case_5_10, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 4));
+ gcc_jit_block_end_with_return (
+ b_default, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_block_end_with_switch:"
+ " duplicate (or overlapping) cases values:"
+ " case 1: case (int)5 ... (int)10: goto case_5_10;"
+ " overlaps case (int)0 ... (int)5: goto case_0_5;");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-non-const-label.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-non-const-label.c
new file mode 100644
index 00000000000..39538183f00
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-non-const-label.c
@@ -0,0 +1,80 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ {
+ switch (x)
+ {
+ case x:
+ return 3;
+
+ default:
+ return 10;
+ }
+ }
+ and verify that we get a sane error about the non-const
+ case.
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *return_type = t_int;
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (ctxt, NULL, t_int, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ 1, params, 0);
+
+ gcc_jit_block *b_initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block *b_default =
+ gcc_jit_function_new_block (func, "default");
+ gcc_jit_block *b_case_x =
+ gcc_jit_function_new_block (func, "case_x");
+
+ /* Erroneous use of non-const x for a case. */
+ gcc_jit_case *cases[1] = {
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_param_as_rvalue (x),
+ gcc_jit_param_as_rvalue (x),
+ b_case_x)
+ };
+
+ gcc_jit_block_end_with_switch (
+ b_initial, NULL,
+ gcc_jit_param_as_rvalue (x),
+ b_default,
+ 1,
+ cases);
+ gcc_jit_block_end_with_return (
+ b_case_x, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3));
+ gcc_jit_block_end_with_return (
+ b_default, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_context_new_case:"
+ " min_value is not a constant: x");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-non-integer-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-non-integer-type.c
new file mode 100644
index 00000000000..5d442862c08
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-non-integer-type.c
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ {
+ switch (x)
+ {
+ case 0.f ... 5.f:
+ return 3;
+ default:
+ return 10;
+ }
+ }
+ and verify that the floating-point case is an error.
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *t_float =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+ gcc_jit_type *return_type = t_int;
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (ctxt, NULL, t_int, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ 1, params, 0);
+
+ gcc_jit_block *b_initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block *b_default =
+ gcc_jit_function_new_block (func, "default");
+ gcc_jit_block *b_case_0 =
+ gcc_jit_function_new_block (func, "case_0");
+
+ /* Note the erroneous use of "t_float" here. */
+ gcc_jit_case *cases[1] = {
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_float, 0),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_float, 5),
+ b_case_0)
+ };
+
+ gcc_jit_block_end_with_switch (
+ b_initial, NULL,
+ gcc_jit_param_as_rvalue (x),
+ b_default,
+ 1,
+ cases);
+
+ gcc_jit_block_end_with_return (
+ b_case_0, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3));
+ gcc_jit_block_end_with_return (
+ b_default, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_context_new_case:"
+ " min_value: (float)0 (type: float) is not of integer type");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-reversed-endpoints.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-reversed-endpoints.c
new file mode 100644
index 00000000000..a84d9f33f3d
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_case-reversed-endpoints.c
@@ -0,0 +1,80 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ {
+ switch (x)
+ {
+ case 5 ... 0:
+ return 3;
+
+ default:
+ return 10;
+ }
+ }
+ and verify that we get an error about the reversed endpoints
+ in the range.
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *return_type = t_int;
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (ctxt, NULL, t_int, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ 1, params, 0);
+
+ gcc_jit_block *b_initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block *b_default =
+ gcc_jit_function_new_block (func, "default");
+ gcc_jit_block *b_case_5_0 =
+ gcc_jit_function_new_block (func, "case_5_0");
+
+ gcc_jit_case *cases[1] = {
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 5),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 0),
+ b_case_5_0)
+ };
+
+ gcc_jit_block_end_with_switch (
+ b_initial, NULL,
+ gcc_jit_param_as_rvalue (x),
+ b_default,
+ 1,
+ cases);
+
+ gcc_jit_block_end_with_return (
+ b_case_5_0, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3));
+ gcc_jit_block_end_with_return (
+ b_default, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_context_new_case:"
+ " min_value: (int)5 > max_value: (int)0");
+}
diff --git a/gcc/testsuite/jit.dg/test-extra-options.c b/gcc/testsuite/jit.dg/test-extra-options.c
new file mode 100644
index 00000000000..37398349fed
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-extra-options.c
@@ -0,0 +1,136 @@
+/* Testcase for gcc_jit_context_add_command_line_option (PR jit/66628). */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+#ifndef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option
+#error LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option was not defined
+#endif
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ gcc_jit_context_add_command_line_option (ctxt, "-ffast-math");
+ gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm");
+
+ /* Let's try to inject the equivalent of:
+
+ double
+ my_dot_product (int n, double *a, double *b)
+ {
+ double result = 0.;
+ for (int i = 0; i < n; i++)
+ result += a[i] * b[i];
+ return result
+ }
+
+ and see what the optimizer can do. */
+ gcc_jit_type *val_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+ gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (val_type);
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+ gcc_jit_type *return_type = val_type;
+ gcc_jit_param *param_n =
+ gcc_jit_context_new_param (ctxt, NULL, int_type, "n");
+ gcc_jit_param *param_a =
+ gcc_jit_context_new_param (ctxt, NULL, ptr_type, "a");
+ gcc_jit_param *param_b =
+ gcc_jit_context_new_param (ctxt, NULL, ptr_type, "b");
+ gcc_jit_param *params[3] = {param_n, param_a, param_b};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "my_dot_product",
+ 3, params, 0);
+
+ gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial");
+ gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test");
+ gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body");
+ gcc_jit_block *final = gcc_jit_function_new_block (func, "final");
+
+ /* Build: "double result = 0.;" */
+ gcc_jit_lvalue *result =
+ gcc_jit_function_new_local (func, NULL, val_type, "result");
+
+ gcc_jit_block_add_assignment (initial, NULL,
+ result, gcc_jit_context_zero (ctxt, val_type));
+
+ /* Build: "for (int i = 0; i < n; i++)" */
+ gcc_jit_lvalue *i =
+ gcc_jit_function_new_local (func, NULL, int_type, "i");
+ gcc_jit_block_add_assignment (initial, NULL,
+ i, gcc_jit_context_zero (ctxt, int_type));
+
+ gcc_jit_block_end_with_jump (initial, NULL, loop_test);
+
+ gcc_jit_block_end_with_conditional (
+ loop_test, NULL,
+
+ /* (i < n) */
+ gcc_jit_context_new_comparison (
+ ctxt, NULL,
+ GCC_JIT_COMPARISON_LT,
+ gcc_jit_lvalue_as_rvalue (i),
+ gcc_jit_param_as_rvalue (param_n)),
+
+ loop_body,
+ final);
+
+ /* Build: "result += a[i] * b[i];" */
+ gcc_jit_block_add_assignment_op (
+ loop_body, NULL,
+ result,
+ GCC_JIT_BINARY_OP_PLUS,
+ gcc_jit_context_new_binary_op (
+ ctxt, NULL,
+ GCC_JIT_BINARY_OP_MULT,
+ val_type,
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_context_new_array_access (
+ ctxt, NULL,
+ gcc_jit_param_as_rvalue (param_a),
+ gcc_jit_lvalue_as_rvalue (i))),
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_context_new_array_access (
+ ctxt, NULL,
+ gcc_jit_param_as_rvalue (param_b),
+ gcc_jit_lvalue_as_rvalue (i)))));
+
+ /* Build: "i++" */
+ gcc_jit_block_add_assignment_op (
+ loop_body, NULL,
+ i,
+ GCC_JIT_BINARY_OP_PLUS,
+ gcc_jit_context_one (ctxt, int_type));
+
+ gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
+
+ /* Build: "return result;" */
+ gcc_jit_block_end_with_return (
+ final,
+ NULL,
+ gcc_jit_lvalue_as_rvalue (result));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef double (*my_dot_product_fn_type) (int n, double *a, double *b);
+ CHECK_NON_NULL (result);
+
+ my_dot_product_fn_type my_dot_product =
+ (my_dot_product_fn_type)gcc_jit_result_get_code (result,
+ "my_dot_product");
+ CHECK_NON_NULL (my_dot_product);
+ double test_array[] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};
+ double val = my_dot_product (10, test_array, test_array);
+ note ("my_dot_product returned: %f", val);
+ CHECK_VALUE (val, 385.0);
+}
diff --git a/gcc/testsuite/jit.dg/test-switch.c b/gcc/testsuite/jit.dg/test-switch.c
new file mode 100644
index 00000000000..74088c81f29
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-switch.c
@@ -0,0 +1,147 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* Quote from here in docs/topics/functions.rst. */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ {
+ switch (x)
+ {
+ case 0 ... 5:
+ return 3;
+
+ case 25 ... 27:
+ return 4;
+
+ case -42 ... -17:
+ return 83;
+
+ case 40:
+ return 8;
+
+ default:
+ return 10;
+ }
+ }
+ */
+ gcc_jit_type *t_int =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *return_type = t_int;
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (ctxt, NULL, t_int, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ 1, params, 0);
+
+ gcc_jit_block *b_initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block *b_default =
+ gcc_jit_function_new_block (func, "default");
+ gcc_jit_block *b_case_0_5 =
+ gcc_jit_function_new_block (func, "case_0_5");
+ gcc_jit_block *b_case_25_27 =
+ gcc_jit_function_new_block (func, "case_25_27");
+ gcc_jit_block *b_case_m42_m17 =
+ gcc_jit_function_new_block (func, "case_m42_m17");
+ gcc_jit_block *b_case_40 =
+ gcc_jit_function_new_block (func, "case_40");
+
+ gcc_jit_case *cases[4] = {
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 0),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 5),
+ b_case_0_5),
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 25),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 27),
+ b_case_25_27),
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -42),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -17),
+ b_case_m42_m17),
+ gcc_jit_context_new_case (
+ ctxt,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40),
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40),
+ b_case_40)
+ };
+ gcc_jit_block_end_with_switch (
+ b_initial, NULL,
+ gcc_jit_param_as_rvalue (x),
+ b_default,
+ 4, cases);
+
+ gcc_jit_block_end_with_return (
+ b_case_0_5, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3));
+ gcc_jit_block_end_with_return (
+ b_case_25_27, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 4));
+ gcc_jit_block_end_with_return (
+ b_case_m42_m17, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 83));
+ gcc_jit_block_end_with_return (
+ b_case_40, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 8));
+ gcc_jit_block_end_with_return (
+ b_default, NULL,
+ gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10));
+}
+
+/* Quote up to here in docs/topics/functions.rst. */
+
+static int
+c_test_switch (int x)
+{
+ switch (x)
+ {
+ case 0 ... 5:
+ return 3;
+ case 25 ... 27:
+ return 4;
+ case -42 ... -17:
+ return 83;
+ case 40:
+ return 8;
+ default:
+ return 10;
+ }
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*test_switch_type) (int);
+ CHECK_NON_NULL (result);
+ test_switch_type test_switch =
+ (test_switch_type)gcc_jit_result_get_code (result, "test_switch");
+ CHECK_NON_NULL (test_switch);
+
+ int i;
+
+ for (i = -255; i < 255; i++)
+ {
+ int val = test_switch (i);
+ int exp = c_test_switch (i);
+ if (val != exp)
+ fail ("test_switch (%i) returned: %i; expected; %i", i, val, exp);
+ }
+}
diff --git a/gcc/testsuite/jit.dg/test-switch.cc b/gcc/testsuite/jit.dg/test-switch.cc
new file mode 100644
index 00000000000..862f7a8f72b
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-switch.cc
@@ -0,0 +1,118 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit++.h"
+
+#include "harness.h"
+
+/* Quote from here in docs/cp/topics/functions.rst. */
+
+void
+create_code (gcc_jit_context *c_ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int
+ test_switch (int x)
+ {
+ switch (x)
+ {
+ case 0 ... 5:
+ return 3;
+
+ case 25 ... 27:
+ return 4;
+
+ case -42 ... -17:
+ return 83;
+
+ case 40:
+ return 8;
+
+ default:
+ return 10;
+ }
+ }
+ */
+ gccjit::context ctxt (c_ctxt);
+ gccjit::type t_int = ctxt.get_type (GCC_JIT_TYPE_INT);
+ gccjit::type return_type = t_int;
+ gccjit::param x = ctxt.new_param (t_int, "x");
+ std::vector <gccjit::param> params;
+ params.push_back (x);
+ gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "test_switch",
+ params, 0);
+
+ gccjit::block b_initial = func.new_block ("initial");
+
+ gccjit::block b_default = func.new_block ("default");
+ gccjit::block b_case_0_5 = func.new_block ("case_0_5");
+ gccjit::block b_case_25_27 = func.new_block ("case_25_27");
+ gccjit::block b_case_m42_m17 = func.new_block ("case_m42_m17");
+ gccjit::block b_case_40 = func.new_block ("case_40");
+
+ std::vector <gccjit::case_> cases;
+ cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 0),
+ ctxt.new_rvalue (t_int, 5),
+ b_case_0_5));
+ cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 25),
+ ctxt.new_rvalue (t_int, 27),
+ b_case_25_27));
+ cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, -42),
+ ctxt.new_rvalue (t_int, -17),
+ b_case_m42_m17));
+ cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 40),
+ ctxt.new_rvalue (t_int, 40),
+ b_case_40));
+ b_initial.end_with_switch (x,
+ b_default,
+ cases);
+
+ b_case_0_5.end_with_return (ctxt.new_rvalue (t_int, 3));
+ b_case_25_27.end_with_return (ctxt.new_rvalue (t_int, 4));
+ b_case_m42_m17.end_with_return (ctxt.new_rvalue (t_int, 83));
+ b_case_40.end_with_return (ctxt.new_rvalue (t_int, 8));
+ b_default.end_with_return (ctxt.new_rvalue (t_int, 10));
+}
+
+/* Quote up to here in docs/cp/topics/functions.rst. */
+
+static int
+c_test_switch (int x)
+{
+ switch (x)
+ {
+ case 0 ... 5:
+ return 3;
+ case 25 ... 27:
+ return 4;
+ case -42 ... -17:
+ return 83;
+ case 40:
+ return 8;
+ default:
+ return 10;
+ }
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*test_switch_type) (int);
+ CHECK_NON_NULL (result);
+ test_switch_type test_switch =
+ (test_switch_type)gcc_jit_result_get_code (result, "test_switch");
+ CHECK_NON_NULL (test_switch);
+
+ int i;
+
+ for (i = -255; i < 255; i++)
+ {
+ int val = test_switch (i);
+ int exp = c_test_switch (i);
+ if (val != exp)
+ fail ("test_switch (%i) returned: %i; expected; %i", i, val, exp);
+ }
+}
diff --git a/gcc/testsuite/jit.dg/test-validly-unreachable-block.c b/gcc/testsuite/jit.dg/test-validly-unreachable-block.c
new file mode 100644
index 00000000000..2664818992a
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-validly-unreachable-block.c
@@ -0,0 +1,51 @@
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ void
+ test_fn ()
+ {
+ return;
+
+ return;
+ }
+ where the second block is unreachable, but have it
+ survive validation (PR jit/66546).
+ */
+ gcc_jit_context_set_bool_allow_unreachable_blocks (ctxt, 1);
+
+ gcc_jit_type *void_t =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+ /* Build the test_fn. */
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_t,
+ "test_fn",
+ 0, NULL,
+ 0);
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (test_fn, "a");
+ gcc_jit_block *unreachable =
+ gcc_jit_function_new_block (test_fn, "b");
+
+ gcc_jit_block_end_with_void_return (initial, NULL);
+
+ gcc_jit_block_end_with_void_return (unreachable, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ /* Ensure that the "unreachable blocks" validator was ignored. */
+ CHECK_NON_NULL (result);
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 573b144a138..1fc5bd92d83 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -112,10 +112,6 @@ along with GCC; see the file COPYING3. If not see
declarations for e.g. AIX 4.x. */
#endif
-#ifndef HAVE_prologue
-#define HAVE_prologue 0
-#endif
-
#include <new>
static void general_init (const char *, bool);
@@ -1660,7 +1656,7 @@ process_options (void)
/* Do not use IPA optimizations for register allocation if profiler is active
or port does not emit prologue and epilogue as RTL. */
- if (profile_flag || !HAVE_prologue || !HAVE_epilogue)
+ if (profile_flag || !targetm.have_prologue () || !targetm.have_epilogue ())
flag_ipa_ra = 0;
/* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index ab77f32372a..21ed17b4caf 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1788,60 +1788,62 @@ try_transform_to_exit_first_loop_alt (struct loop *loop,
nit, build_one_cst (nit_type));
gcc_assert (TREE_CODE (alt_bound) == INTEGER_CST);
+ transform_to_exit_first_loop_alt (loop, reduction_list, alt_bound);
+ return true;
}
else
{
/* Todo: Figure out if we can trigger this, if it's worth to handle
optimally, and if we can handle it optimally. */
+ return false;
}
}
- else
- {
- gcc_assert (TREE_CODE (nit) == SSA_NAME);
- gimple def = SSA_NAME_DEF_STMT (nit);
+ gcc_assert (TREE_CODE (nit) == SSA_NAME);
- if (def
- && is_gimple_assign (def)
- && gimple_assign_rhs_code (def) == PLUS_EXPR)
- {
- tree op1 = gimple_assign_rhs1 (def);
- tree op2 = gimple_assign_rhs2 (def);
- if (integer_minus_onep (op1))
- alt_bound = op2;
- else if (integer_minus_onep (op2))
- alt_bound = op1;
- }
+ /* Variable nit is the loop bound as returned by canonicalize_loop_ivs, for an
+ iv with base 0 and step 1 that is incremented in the latch, like this:
- /* There is a number of test-cases for which we don't get an alt_bound
- here: they're listed here, with the lhs of the last stmt as the nit:
+ <bb header>:
+ # iv_1 = PHI <0 (preheader), iv_2 (latch)>
+ ...
+ if (iv_1 < nit)
+ goto <bb latch>;
+ else
+ goto <bb exit>;
- libgomp.graphite/force-parallel-1.c:
- _21 = (signed long) N_6(D);
- _19 = _21 + -1;
- _7 = (unsigned long) _19;
+ <bb latch>:
+ iv_2 = iv_1 + 1;
+ goto <bb header>;
- libgomp.graphite/force-parallel-2.c:
- _33 = (signed long) N_9(D);
- _16 = _33 + -1;
- _37 = (unsigned long) _16;
+ The range of iv_1 is [0, nit]. The latch edge is taken for
+ iv_1 == [0, nit - 1] and the exit edge is taken for iv_1 == nit. So the
+ number of latch executions is equal to nit.
- libgomp.graphite/force-parallel-5.c:
- <bb 6>:
- # graphite_IV.5_46 = PHI <0(5), graphite_IV.5_47(11)>
- <bb 7>:
- _33 = (unsigned long) graphite_IV.5_46;
+ The function max_loop_iterations gives us the maximum number of latch
+ executions, so it gives us the maximum value of nit. */
+ widest_int nit_max;
+ if (!max_loop_iterations (loop, &nit_max))
+ return false;
- g++.dg/tree-ssa/pr34355.C:
- _2 = (unsigned int) i_9;
- _3 = 4 - _2;
+ /* Check if nit + 1 overflows. */
+ widest_int type_max = wi::to_widest (TYPE_MAXVAL (nit_type));
+ if (!wi::lts_p (nit_max, type_max))
+ return false;
- gcc.dg/pr53849.c:
- _5 = d.0_11 + -2;
- _18 = (unsigned int) _5;
+ gimple def = SSA_NAME_DEF_STMT (nit);
- We will be able to handle some of these cases, if we can determine when
- it's safe to look past casts. */
+ /* Try to find nit + 1, in the form of n in an assignment nit = n - 1. */
+ if (def
+ && is_gimple_assign (def)
+ && gimple_assign_rhs_code (def) == PLUS_EXPR)
+ {
+ tree op1 = gimple_assign_rhs1 (def);
+ tree op2 = gimple_assign_rhs2 (def);
+ if (integer_minus_onep (op1))
+ alt_bound = op2;
+ else if (integer_minus_onep (op2))
+ alt_bound = op1;
}
if (alt_bound == NULL_TREE)
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 08afde2c586..fae679fa216 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -1386,10 +1386,6 @@ record_sub_use (struct ivopts_data *data, tree *use_p,
pre->next = use;
}
- /* To avoid showing ssa name in the dumps, if it was not reset by the
- caller. */
- iv->ssa_name = NULL_TREE;
-
return use;
}
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 66d3ba85b57..4f4cf4ead5b 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -4857,7 +4857,10 @@ vect_setup_realignment (gimple stmt, gimple_stmt_iterator *gsi,
ptr = vect_create_data_ref_ptr (stmt, vectype, loop_for_initial_load,
NULL_TREE, &init_addr, NULL, &inc,
true, &inv_p);
- new_temp = copy_ssa_name (ptr);
+ if (TREE_CODE (ptr) == SSA_NAME)
+ new_temp = copy_ssa_name (ptr);
+ else
+ new_temp = make_ssa_name (TREE_TYPE (ptr));
new_stmt = gimple_build_assign
(new_temp, BIT_AND_EXPR, ptr,
build_int_cst (TREE_TYPE (ptr),
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index ec6d2c3e139..db1df37d471 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -5359,7 +5359,9 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
/* In the case of post-in/decrement tests like if (i++) ... and uses
of the in/decremented value on the edge the extra name we want to
assert for is not on the def chain of the name compared. Instead
- it is in the set of use stmts. */
+ it is in the set of use stmts.
+ Similar cases happen for conversions that were simplified through
+ fold_{sign_changed,widened}_comparison. */
if ((comp_code == NE_EXPR
|| comp_code == EQ_EXPR)
&& TREE_CODE (val) == INTEGER_CST)
@@ -5368,29 +5370,37 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
gimple use_stmt;
FOR_EACH_IMM_USE_STMT (use_stmt, ui, name)
{
- /* Cut off to use-stmts that are in the predecessor. */
- if (gimple_bb (use_stmt) != e->src)
- continue;
-
if (!is_gimple_assign (use_stmt))
continue;
- enum tree_code code = gimple_assign_rhs_code (use_stmt);
- if (code != PLUS_EXPR
- && code != MINUS_EXPR)
+ /* Cut off to use-stmts that are dominating the predecessor. */
+ if (!dominated_by_p (CDI_DOMINATORS, e->src, gimple_bb (use_stmt)))
continue;
- tree cst = gimple_assign_rhs2 (use_stmt);
- if (TREE_CODE (cst) != INTEGER_CST)
+ tree name2 = gimple_assign_lhs (use_stmt);
+ if (TREE_CODE (name2) != SSA_NAME
+ || !live_on_edge (e, name2))
continue;
- tree name2 = gimple_assign_lhs (use_stmt);
- if (live_on_edge (e, name2))
+ enum tree_code code = gimple_assign_rhs_code (use_stmt);
+ tree cst;
+ if (code == PLUS_EXPR
+ || code == MINUS_EXPR)
{
+ cst = gimple_assign_rhs2 (use_stmt);
+ if (TREE_CODE (cst) != INTEGER_CST)
+ continue;
cst = int_const_binop (code, val, cst);
- register_new_assert_for (name2, name2, comp_code, cst,
- NULL, e, bsi);
}
+ else if (CONVERT_EXPR_CODE_P (code))
+ cst = fold_convert (TREE_TYPE (name2), val);
+ else
+ continue;
+
+ if (TREE_OVERFLOW_P (cst))
+ cst = drop_tree_overflow (cst);
+ register_new_assert_for (name2, name2, comp_code, cst,
+ NULL, e, bsi);
}
}
diff --git a/gcc/typed-splay-tree.h b/gcc/typed-splay-tree.h
new file mode 100644
index 00000000000..784986219e1
--- /dev/null
+++ b/gcc/typed-splay-tree.h
@@ -0,0 +1,135 @@
+/* A typesafe wrapper around libiberty's splay-tree.h.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_TYPED_SPLAY_TREE_H
+#define GCC_TYPED_SPLAY_TREE_H
+
+#include "splay-tree.h"
+
+/* Typesafe wrapper around libiberty's splay-tree.h. */
+template <typename KEY_TYPE, typename VALUE_TYPE>
+class typed_splay_tree
+{
+ public:
+ typedef KEY_TYPE key_type;
+ typedef VALUE_TYPE value_type;
+
+ typedef int (*compare_fn) (key_type, key_type);
+ typedef void (*delete_key_fn) (key_type);
+ typedef void (*delete_value_fn) (value_type);
+
+ typed_splay_tree (compare_fn,
+ delete_key_fn,
+ delete_value_fn);
+ ~typed_splay_tree ();
+
+ value_type lookup (key_type k);
+ value_type predecessor (key_type k);
+ value_type successor (key_type k);
+ void insert (key_type k, value_type v);
+
+ private:
+ static value_type node_to_value (splay_tree_node node);
+
+ private:
+ ::splay_tree m_inner;
+};
+
+/* Constructor for typed_splay_tree <K, V>. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline typed_splay_tree<KEY_TYPE, VALUE_TYPE>::
+ typed_splay_tree (compare_fn compare_fn,
+ delete_key_fn delete_key_fn,
+ delete_value_fn delete_value_fn)
+{
+ m_inner = splay_tree_new ((splay_tree_compare_fn)compare_fn,
+ (splay_tree_delete_key_fn)delete_key_fn,
+ (splay_tree_delete_value_fn)delete_value_fn);
+}
+
+/* Destructor for typed_splay_tree <K, V>. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline typed_splay_tree<KEY_TYPE, VALUE_TYPE>::
+ ~typed_splay_tree ()
+{
+ splay_tree_delete (m_inner);
+}
+
+/* Lookup KEY, returning a value if present, and NULL
+ otherwise. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::lookup (key_type key)
+{
+ splay_tree_node node = splay_tree_lookup (m_inner, (splay_tree_key)key);
+ return node_to_value (node);
+}
+
+/* Return the immediate predecessor of KEY, or NULL if there is no
+ predecessor. KEY need not be present in the tree. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::predecessor (key_type key)
+{
+ splay_tree_node node = splay_tree_predecessor (m_inner, (splay_tree_key)key);
+ return node_to_value (node);
+}
+
+/* Return the immediate successor of KEY, or NULL if there is no
+ successor. KEY need not be present in the tree. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::successor (key_type k)
+{
+ splay_tree_node node = splay_tree_successor (m_inner, (splay_tree_key)k);
+ return node_to_value (node);
+}
+
+/* Insert a new node (associating KEY with VALUE). If a
+ previous node with the indicated KEY exists, its data is replaced
+ with the new value. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::insert (key_type key,
+ value_type value)
+{
+ splay_tree_insert (m_inner,
+ (splay_tree_key)key,
+ (splay_tree_value)value);
+}
+
+/* Internal function for converting from splay_tree_node to
+ VALUE_TYPE. */
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::node_to_value (splay_tree_node node)
+{
+ if (node)
+ return (value_type)node->value;
+ else
+ return 0;
+}
+
+#endif /* GCC_TYPED_SPLAY_TREE_H */
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index f373dad5130..4e2980222b3 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,24 @@
+2015-06-30 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement N4197 - Adding u8 character literals
+ * include/cpplib.h (UTF8CHAR, UTF8CHAR_USERDEF): New cpp tokens;
+ (struct cpp_options): Add utf8_char_literals.
+ * init.c (struct lang_flags): Add utf8_char_literals;
+ (struct lang_flags lang_defaults): Add column for utf8_char_literals.
+ * macro.c (stringify_arg()): Treat CPP_UTF8CHAR token;
+ * expr.c (cpp_userdef_char_remove_type(), cpp_userdef_char_add_type()):
+ Treat CPP_UTF8CHAR_USERDEF, CPP_UTF8CHAR tokens;
+ (cpp_userdef_char_p()): Treat CPP_UTF8CHAR_USERDEF token;
+ (eval_token(), _cpp_parse_expr()): Treat CPP_UTF8CHAR token.
+ * lex.c (lex_string(), _cpp_lex_direct()): Include CPP_UTF8CHAR tokens.
+ * charset.c (converter_for_type(), cpp_interpret_charconst()):
+ Treat CPP_UTF8CHAR token.
+
+2015-06-30 Uros Bizjak <ubizjak@gmail.com>
+
+ * lex.c (search_line_sse42) [__GCC_ASM_FLAG_OUTPUTS__]: New main
+ loop using asm flag outputs.
+
2015-06-08 Marek Polacek <polacek@redhat.com>
PR c/66415
diff --git a/libcpp/charset.c b/libcpp/charset.c
index b4276380658..8e92bc65f90 100644
--- a/libcpp/charset.c
+++ b/libcpp/charset.c
@@ -1355,6 +1355,7 @@ converter_for_type (cpp_reader *pfile, enum cpp_ttype type)
{
default:
return pfile->narrow_cset_desc;
+ case CPP_UTF8CHAR:
case CPP_UTF8STRING:
return pfile->utf8_cset_desc;
case CPP_CHAR16:
@@ -1611,11 +1612,12 @@ cpp_interpret_charconst (cpp_reader *pfile, const cpp_token *token,
unsigned int *pchars_seen, int *unsignedp)
{
cpp_string str = { 0, 0 };
- bool wide = (token->type != CPP_CHAR);
+ bool wide = (token->type != CPP_CHAR && token->type != CPP_UTF8CHAR);
+ int u8 = 2 * int(token->type == CPP_UTF8CHAR);
cppchar_t result;
- /* an empty constant will appear as L'', u'', U'' or '' */
- if (token->val.str.len == (size_t) (2 + wide))
+ /* An empty constant will appear as L'', u'', U'', u8'', or '' */
+ if (token->val.str.len == (size_t) (2 + wide + u8))
{
cpp_error (pfile, CPP_DL_ERROR, "empty character constant");
return 0;
diff --git a/libcpp/expr.c b/libcpp/expr.c
index b8e88c50f33..3dc5c0bf238 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -307,6 +307,8 @@ cpp_userdef_char_remove_type (enum cpp_ttype type)
return CPP_CHAR16;
else if (type == CPP_CHAR32_USERDEF)
return CPP_CHAR32;
+ else if (type == CPP_UTF8CHAR_USERDEF)
+ return CPP_UTF8CHAR;
else
return type;
}
@@ -325,6 +327,8 @@ cpp_userdef_char_add_type (enum cpp_ttype type)
return CPP_CHAR16_USERDEF;
else if (type == CPP_CHAR32)
return CPP_CHAR32_USERDEF;
+ else if (type == CPP_UTF8CHAR)
+ return CPP_UTF8CHAR_USERDEF;
else
return type;
}
@@ -350,7 +354,8 @@ cpp_userdef_char_p (enum cpp_ttype type)
if (type == CPP_CHAR_USERDEF
|| type == CPP_WCHAR_USERDEF
|| type == CPP_CHAR16_USERDEF
- || type == CPP_CHAR32_USERDEF)
+ || type == CPP_CHAR32_USERDEF
+ || type == CPP_UTF8CHAR_USERDEF)
return true;
else
return false;
@@ -1029,6 +1034,7 @@ eval_token (cpp_reader *pfile, const cpp_token *token,
case CPP_CHAR:
case CPP_CHAR16:
case CPP_CHAR32:
+ case CPP_UTF8CHAR:
{
cppchar_t cc = cpp_interpret_charconst (pfile, token,
&temp, &unsignedp);
@@ -1214,6 +1220,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
case CPP_WCHAR:
case CPP_CHAR16:
case CPP_CHAR32:
+ case CPP_UTF8CHAR:
case CPP_NAME:
case CPP_HASH:
if (!want_value)
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 1b1a53ce599..5eaea6b60d7 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -119,6 +119,7 @@ struct _cpp_file;
TK(WCHAR, LITERAL) /* L'char' */ \
TK(CHAR16, LITERAL) /* u'char' */ \
TK(CHAR32, LITERAL) /* U'char' */ \
+ TK(UTF8CHAR, LITERAL) /* u8'char' */ \
TK(OTHER, LITERAL) /* stray punctuation */ \
\
TK(STRING, LITERAL) /* "string" */ \
@@ -133,6 +134,7 @@ struct _cpp_file;
TK(WCHAR_USERDEF, LITERAL) /* L'char'_suffix - C++-0x */ \
TK(CHAR16_USERDEF, LITERAL) /* u'char'_suffix - C++-0x */ \
TK(CHAR32_USERDEF, LITERAL) /* U'char'_suffix - C++-0x */ \
+ TK(UTF8CHAR_USERDEF, LITERAL) /* u8'char'_suffix - C++-0x */ \
TK(STRING_USERDEF, LITERAL) /* "string"_suffix - C++-0x */ \
TK(WSTRING_USERDEF, LITERAL) /* L"string"_suffix - C++-0x */ \
TK(STRING16_USERDEF, LITERAL) /* u"string"_suffix - C++-0x */ \
@@ -339,6 +341,9 @@ struct cpp_options
/* Nonzero means process u/U prefix literals (UTF-16/32). */
unsigned char uliterals;
+ /* Nonzero means process u8 prefixed character literals (UTF-8). */
+ unsigned char utf8_char_literals;
+
/* Nonzero means process r/R raw strings. If this is set, uliterals
must be set as well. */
unsigned char rliterals;
diff --git a/libcpp/init.c b/libcpp/init.c
index 1ebd709af2c..2d5626fd9ab 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -90,26 +90,27 @@ struct lang_flags
char binary_constants;
char digit_separators;
char trigraphs;
+ char utf8_char_literals;
};
static const struct lang_flags lang_defaults[] =
-{ /* c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig */
- /* GNUC89 */ { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
- /* GNUC99 */ { 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- /* GNUC11 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0 },
- /* STDC89 */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
- /* STDC94 */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
- /* STDC99 */ { 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
- /* STDC11 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 },
- /* GNUCXX */ { 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
- /* CXX98 */ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
- /* GNUCXX11 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0 },
- /* CXX11 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1 },
- /* GNUCXX14 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 },
- /* CXX14 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
- /* GNUCXX1Z */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 },
- /* CXX1Z */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- /* ASM */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+{ /* c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit */
+ /* GNUC89 */ { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
+ /* GNUC99 */ { 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
+ /* GNUC11 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
+ /* STDC89 */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0 },
+ /* STDC94 */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 },
+ /* STDC99 */ { 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 },
+ /* STDC11 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0 },
+ /* GNUCXX */ { 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
+ /* CXX98 */ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 },
+ /* GNUCXX11 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0 },
+ /* CXX11 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 },
+ /* GNUCXX14 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 },
+ /* CXX14 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+ /* GNUCXX1Z */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1 },
+ /* CXX1Z */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1 },
+ /* ASM */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
/* Sets internal flags correctly for a given language. */
@@ -133,6 +134,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
CPP_OPTION (pfile, binary_constants) = l->binary_constants;
CPP_OPTION (pfile, digit_separators) = l->digit_separators;
CPP_OPTION (pfile, trigraphs) = l->trigraphs;
+ CPP_OPTION (pfile, utf8_char_literals) = l->utf8_char_literals;
}
/* Initialize library global state. */
diff --git a/libcpp/lex.c b/libcpp/lex.c
index c7296a110b6..8f2bdc80e11 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -450,15 +450,33 @@ search_line_sse42 (const uchar *s, const uchar *end)
s = (const uchar *)((si + 16) & -16);
}
- /* Main loop, processing 16 bytes at a time. By doing the whole loop
- in inline assembly, we can make proper use of the flags set. */
- __asm ( "sub $16, %1\n"
- " .balign 16\n"
+ /* Main loop, processing 16 bytes at a time. */
+#ifdef __GCC_ASM_FLAG_OUTPUTS__
+ while (1)
+ {
+ char f;
+
+ /* By using inline assembly instead of the builtin,
+ we can use the result, as well as the flags set. */
+ __asm ("%vpcmpestri\t$0, %2, %3"
+ : "=c"(index), "=@ccc"(f)
+ : "m"(*s), "x"(search), "a"(4), "d"(16));
+ if (f)
+ break;
+
+ s += 16;
+ }
+#else
+ s -= 16;
+ /* By doing the whole loop in inline assembly,
+ we can make proper use of the flags set. */
+ __asm ( ".balign 16\n"
"0: add $16, %1\n"
- " %vpcmpestri $0, (%1), %2\n"
+ " %vpcmpestri\t$0, (%1), %2\n"
" jnc 0b"
: "=&c"(index), "+r"(s)
: "x"(search), "a"(4), "d"(16));
+#endif
found:
return s + index;
@@ -1840,7 +1858,8 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
else if (terminator == '\'')
type = (*base == 'L' ? CPP_WCHAR :
*base == 'U' ? CPP_CHAR32 :
- *base == 'u' ? CPP_CHAR16 : CPP_CHAR);
+ *base == 'u' ? (base[1] == '8' ? CPP_UTF8CHAR : CPP_CHAR16)
+ : CPP_CHAR);
else
terminator = '>', type = CPP_HEADER_NAME;
@@ -2385,7 +2404,8 @@ _cpp_lex_direct (cpp_reader *pfile)
&& CPP_OPTION (pfile, rliterals))
|| (*buffer->cur == '8'
&& c == 'u'
- && (buffer->cur[1] == '"'
+ && ((buffer->cur[1] == '"' || (buffer->cur[1] == '\''
+ && CPP_OPTION (pfile, utf8_char_literals)))
|| (buffer->cur[1] == 'R' && buffer->cur[2] == '"'
&& CPP_OPTION (pfile, rliterals)))))
{
diff --git a/libcpp/macro.c b/libcpp/macro.c
index f76e10b0b2e..786c21beba3 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -531,7 +531,7 @@ stringify_arg (cpp_reader *pfile, macro_arg *arg)
|| token->type == CPP_WSTRING || token->type == CPP_WCHAR
|| token->type == CPP_STRING32 || token->type == CPP_CHAR32
|| token->type == CPP_STRING16 || token->type == CPP_CHAR16
- || token->type == CPP_UTF8STRING
+ || token->type == CPP_UTF8STRING || token->type == CPP_UTF8CHAR
|| cpp_userdef_string_p (token->type)
|| cpp_userdef_char_p (token->type));
diff --git a/libdecnumber/ChangeLog b/libdecnumber/ChangeLog
index 15e9113feba..2a65d8e790f 100644
--- a/libdecnumber/ChangeLog
+++ b/libdecnumber/ChangeLog
@@ -1,3 +1,7 @@
+2015-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * configure: Regenerated.
+
2015-05-13 Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
* aclocal.m4: Regenerated with automake-1.11.6.
diff --git a/libdecnumber/configure b/libdecnumber/configure
index 2720f46ff7f..964837d28a7 100755
--- a/libdecnumber/configure
+++ b/libdecnumber/configure
@@ -4614,7 +4614,7 @@ else
case $target in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 956038854ec..72c8c7afbb4 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,10 @@
+2015-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config.host: Support i[34567]86-*-elfiamcu target.
+ * config/t-softfp-sfdftf: New file.
+ * config/i386/32/t-iamcu: Likewise.
+ * configure: Regenerated.
+
2015-06-23 James Lemke <jwlemke@codesourcery.com>
libgcc/config/arm/
diff --git a/libgcc/config.host b/libgcc/config.host
index 46666df87da..3a2c75db458 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -562,6 +562,9 @@ x86_64-*-darwin*)
tm_file="$tm_file i386/darwin-lib.h"
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
;;
+i[34567]86-*-elfiamcu)
+ tmake_file="$tmake_file i386/t-crtstuff t-softfp-sfdftf i386/32/t-softfp i386/32/t-iamcu i386/t-softfp t-softfp t-dfprules"
+ ;;
i[34567]86-*-elf*)
tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
;;
diff --git a/libgcc/config/i386/32/t-iamcu b/libgcc/config/i386/32/t-iamcu
new file mode 100644
index 00000000000..7595cdeed84
--- /dev/null
+++ b/libgcc/config/i386/32/t-iamcu
@@ -0,0 +1 @@
+HOST_LIBGCC2_CFLAGS += -mlong-double-80
diff --git a/libgcc/config/t-softfp-sfdftf b/libgcc/config/t-softfp-sfdftf
new file mode 100644
index 00000000000..ed71d2175f0
--- /dev/null
+++ b/libgcc/config/t-softfp-sfdftf
@@ -0,0 +1,5 @@
+softfp_float_modes := sf df tf
+softfp_int_modes := si di
+softfp_extensions := sfdf sftf dftf xftf
+softfp_truncations := dfsf tfsf tfdf tfxf
+softfp_exclude_libgcc2 := n
diff --git a/libgcc/configure b/libgcc/configure
index ce66d1dd312..e22cbcb872a 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -4436,7 +4436,7 @@ else
case $host in
powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
- i?86*-*-gnu* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | \
i?86*-*-mingw* | x86_64*-*-mingw* | \
i?86*-*-cygwin* | x86_64*-*-cygwin*)
enable_decimal_float=yes
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index a01f9b2816c..4e4fcc32e8e 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,67 @@
+2015-06-30 Tom de Vries <tom@codesourcery.com>
+
+ * testsuite/libgomp.oacc-c++/c++.exp: Set DEFAULT_CFLAGS to -O2 if not
+ already set. Use DEFAULT_CFLAGS in dg-runtest.
+ * testsuite/libgomp.oacc-c-c++-common/collapse-3.c: Remove dg-options
+ "-O2".
+
+2015-06-30 Tom de Vries <tom@codesourcery.com>
+
+ * testsuite/libgomp.c++/c++.exp: Set DEFAULT_CFLAGS to -O2 if not
+ already set. Use DEFAULT_CFLAGS in dg-runtest.
+ * testsuite/libgomp.c++/atomic-16.C: Remove dg-options "-O2 -fopenmp".
+ * testsuite/libgomp.c++/pr64824.C: Same.
+ * testsuite/libgomp.c++/pr64868.C: Same.
+ * testsuite/libgomp.c++/pr66199-1.C: Same.
+ * testsuite/libgomp.c++/pr66199-2.C: Same.
+ * testsuite/libgomp.c++/target-2.C: Same.
+ * testsuite/libgomp.c++/for-7.C: Use dg-additional-options for
+ -std=<standard> option.
+ * testsuite/libgomp.c++/udr-11.C: Same.
+ * testsuite/libgomp.c++/udr-12.C: Same.
+ * testsuite/libgomp.c++/udr-13.C: Same.
+ * testsuite/libgomp.c++/udr-14.C: Same.
+ * testsuite/libgomp.c++/udr-15.C: Same.
+ * testsuite/libgomp.c++/udr-16.C: Same.
+ * testsuite/libgomp.c++/udr-17.C: Same.
+ * testsuite/libgomp.c++/udr-18.C: Same.
+ * testsuite/libgomp.c++/udr-19.C: Same.
+ * testsuite/libgomp.c++/atomic-1.C: Remove dg-options "-O2".
+ * testsuite/libgomp.c++/simd-1.C: Same.
+ * testsuite/libgomp.c++/simd-2.C: Same.
+ * testsuite/libgomp.c++/simd-3.C: Same.
+ * testsuite/libgomp.c++/simd-4.C: Same.
+ * testsuite/libgomp.c++/simd-5.C: Same.
+ * testsuite/libgomp.c++/simd-6.C: Same.
+ * testsuite/libgomp.c++/simd-7.C: Same.
+ * testsuite/libgomp.c++/simd-8.C: Same.
+ * testsuite/libgomp.c++/simd-9.C: Same.
+ * testsuite/libgomp.c++/simd10.C: Same.
+ * testsuite/libgomp.c++/simd11.C: Same.
+ * testsuite/libgomp.c++/simd12.C: Same.
+ * testsuite/libgomp.c++/simd13.C: Same.
+
+2015-06-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/66702
+ * testsuite/libgomp.c++/pr66702-1.C: New test.
+ * testsuite/libgomp.c++/pr66702-2.C: New test.
+
+2015-06-30 Tom de Vries <tom@codesourcery.com>
+
+ * testsuite/libgomp.c/parloops-exit-first-loop-alt-5.c: New test.
+ * testsuite/libgomp.c/parloops-exit-first-loop-alt-6.c: New test.
+ * testsuite/libgomp.c/parloops-exit-first-loop-alt-7.c: New test.
+ * testsuite/libgomp.c/parloops-exit-first-loop-alt.c: Update comment.
+
+2015-06-30 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/66652
+ * testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c (f): Rewrite
+ using restrict pointers.
+ (main): Add arguments to calls to f.
+ * testsuite/libgomp.c/parloops-exit-first-loop-alt.c: Same.
+
2015-06-23 Andreas Tobler <andreast@gcc.gnu.org>
* configure.ac: Fix check for header <sys/sysctl.h>.
diff --git a/libgomp/testsuite/libgomp.c++/atomic-1.C b/libgomp/testsuite/libgomp.c++/atomic-1.C
index 73f6e7c4059..9eecfbbe77d 100644
--- a/libgomp/testsuite/libgomp.c++/atomic-1.C
+++ b/libgomp/testsuite/libgomp.c++/atomic-1.C
@@ -1,6 +1,5 @@
// PR c++/33894
// { dg-do run }
-// { dg-options "-O2" }
extern "C" void abort ();
diff --git a/libgomp/testsuite/libgomp.c++/atomic-16.C b/libgomp/testsuite/libgomp.c++/atomic-16.C
index afccd52bb66..432d36dd7da 100644
--- a/libgomp/testsuite/libgomp.c++/atomic-16.C
+++ b/libgomp/testsuite/libgomp.c++/atomic-16.C
@@ -1,5 +1,4 @@
// PR c/64824
// { dg-do run }
-// { dg-options "-O2 -fopenmp" }
#include "../libgomp.c/atomic-18.c"
diff --git a/libgomp/testsuite/libgomp.c++/c++.exp b/libgomp/testsuite/libgomp.c++/c++.exp
index da42e6213b0..0454f95588e 100644
--- a/libgomp/testsuite/libgomp.c++/c++.exp
+++ b/libgomp/testsuite/libgomp.c++/c++.exp
@@ -11,6 +11,11 @@ if [info exists lang_include_flags] then {
unset lang_include_flags
}
+# If a testcase doesn't have special options, use these.
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS "-O2"
+}
+
# Initialize dg.
dg-init
@@ -60,7 +65,7 @@ if { $lang_test_file_found } {
}
# Main loop.
- dg-runtest $tests "" $libstdcxx_includes
+ dg-runtest $tests "" "$libstdcxx_includes $DEFAULT_CFLAGS"
}
# All done.
diff --git a/libgomp/testsuite/libgomp.c++/for-7.C b/libgomp/testsuite/libgomp.c++/for-7.C
index 9d626c028df..256a1312e4f 100644
--- a/libgomp/testsuite/libgomp.c++/for-7.C
+++ b/libgomp/testsuite/libgomp.c++/for-7.C
@@ -1,6 +1,6 @@
// PR c++/
// { dg-do run }
-// { dg-options "-std=c++0x -fopenmp" }
+// { dg-additional-options "-std=c++0x" }
extern "C" void abort ();
int cnt;
diff --git a/libgomp/testsuite/libgomp.c++/pr64824.C b/libgomp/testsuite/libgomp.c++/pr64824.C
index 348f6d6e0c2..00f23bb728c 100644
--- a/libgomp/testsuite/libgomp.c++/pr64824.C
+++ b/libgomp/testsuite/libgomp.c++/pr64824.C
@@ -1,5 +1,4 @@
// PR c/64824
// { dg-do run }
-// { dg-options "-O2 -fopenmp" }
#include "../libgomp.c/pr64824.c"
diff --git a/libgomp/testsuite/libgomp.c++/pr64868.C b/libgomp/testsuite/libgomp.c++/pr64868.C
index 2d730ac4924..661ec232dd3 100644
--- a/libgomp/testsuite/libgomp.c++/pr64868.C
+++ b/libgomp/testsuite/libgomp.c++/pr64868.C
@@ -1,5 +1,4 @@
// PR c/64868
// { dg-do run }
-// { dg-options "-O2 -fopenmp" }
#include "../libgomp.c/pr64868.c"
diff --git a/libgomp/testsuite/libgomp.c++/pr66199-1.C b/libgomp/testsuite/libgomp.c++/pr66199-1.C
index 2139e11b51c..cb86a60fa26 100644
--- a/libgomp/testsuite/libgomp.c++/pr66199-1.C
+++ b/libgomp/testsuite/libgomp.c++/pr66199-1.C
@@ -1,5 +1,4 @@
// PR middle-end/66199
// { dg-do run }
-// { dg-options "-O2 -fopenmp" }
#include "../libgomp.c/pr66199-1.c"
diff --git a/libgomp/testsuite/libgomp.c++/pr66199-2.C b/libgomp/testsuite/libgomp.c++/pr66199-2.C
index 36392da270a..1dbccb6c0e5 100644
--- a/libgomp/testsuite/libgomp.c++/pr66199-2.C
+++ b/libgomp/testsuite/libgomp.c++/pr66199-2.C
@@ -1,5 +1,4 @@
// PR middle-end/66199
// { dg-do run }
-// { dg-options "-O2 -fopenmp" }
#include "../libgomp.c/pr66199-2.c"
diff --git a/libgomp/testsuite/libgomp.c++/pr66702-1.C b/libgomp/testsuite/libgomp.c++/pr66702-1.C
new file mode 100644
index 00000000000..15772561b1a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/pr66702-1.C
@@ -0,0 +1,49 @@
+// PR middle-end/66702
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+void
+bar (int &a, int &b, int *&c, int &d)
+{
+ volatile int x;
+ int *volatile y;
+ x = a; a = x;
+ x = b; b = x;
+ y = c; c = y;
+ x = d; d = x;
+}
+
+void (*volatile barp) (int &, int &, int *&, int &) = bar;
+
+#pragma omp declare simd uniform(b, c) linear(d:2) aligned(c:32) notinbranch
+int
+foo (int a, int b, int *c, int d)
+{
+ a++;
+ b++;
+ c += 8;
+ d += 2;
+ barp (a, b, c, d);
+ return a + b + *c + d;
+}
+
+volatile int e = 5;
+int c[64] __attribute__((aligned (32)));
+
+int
+main ()
+{
+ int d = 7, r = 0;
+ int b = e;
+ for (int i = 0; i < 64; i++)
+ c[i] = i;
+ #pragma omp simd reduction(+:r) linear(d:2)
+ for (int i = 0; i < 64; i++)
+ {
+ r += foo (i, b, c, d);
+ d += 2;
+ }
+ if (r != 7584)
+ __builtin_abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/pr66702-2.C b/libgomp/testsuite/libgomp.c++/pr66702-2.C
new file mode 100644
index 00000000000..7de3de010a7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/pr66702-2.C
@@ -0,0 +1,34 @@
+// PR middle-end/66702
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+struct S { int s1, s2; };
+struct T { T (); ~T (); int t; };
+
+T::T () : t(0) {}
+T::~T () {}
+
+#pragma omp declare simd uniform(b, c) notinbranch
+__attribute__((noinline)) int
+foo (int a, S b, T c)
+{
+ a++;
+ b.s1++;
+ b.s2++;
+ c.t++;
+ return a + b.s1 + b.s2 + c.t;
+}
+
+int
+main ()
+{
+ int r = 0;
+ S s = { 2, 3 };
+ T t;
+ #pragma omp simd reduction(+:r)
+ for (int i = 0; i < 64; i++)
+ r += foo (i, s, t);
+ if (r != 2592)
+ __builtin_abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-1.C b/libgomp/testsuite/libgomp.c++/simd-1.C
index 16ef159b827..139386f085a 100644
--- a/libgomp/testsuite/libgomp.c++/simd-1.C
+++ b/libgomp/testsuite/libgomp.c++/simd-1.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd-2.C b/libgomp/testsuite/libgomp.c++/simd-2.C
index 6b12415bdce..8205d6449c8 100644
--- a/libgomp/testsuite/libgomp.c++/simd-2.C
+++ b/libgomp/testsuite/libgomp.c++/simd-2.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd-3.C b/libgomp/testsuite/libgomp.c++/simd-3.C
index 1c6d8e01af9..195261d820e 100644
--- a/libgomp/testsuite/libgomp.c++/simd-3.C
+++ b/libgomp/testsuite/libgomp.c++/simd-3.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd-4.C b/libgomp/testsuite/libgomp.c++/simd-4.C
index bdfacc65264..b81f230b25d 100644
--- a/libgomp/testsuite/libgomp.c++/simd-4.C
+++ b/libgomp/testsuite/libgomp.c++/simd-4.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd-5.C b/libgomp/testsuite/libgomp.c++/simd-5.C
index 6c4627e210a..e7cea84548c 100644
--- a/libgomp/testsuite/libgomp.c++/simd-5.C
+++ b/libgomp/testsuite/libgomp.c++/simd-5.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd-6.C b/libgomp/testsuite/libgomp.c++/simd-6.C
index cfc13d0a0f9..fa93dfd5989 100644
--- a/libgomp/testsuite/libgomp.c++/simd-6.C
+++ b/libgomp/testsuite/libgomp.c++/simd-6.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd-7.C b/libgomp/testsuite/libgomp.c++/simd-7.C
index 5a6f4cef7c1..a0bdac5e1b7 100644
--- a/libgomp/testsuite/libgomp.c++/simd-7.C
+++ b/libgomp/testsuite/libgomp.c++/simd-7.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd-8.C b/libgomp/testsuite/libgomp.c++/simd-8.C
index 7c758328529..bc13254fdd3 100644
--- a/libgomp/testsuite/libgomp.c++/simd-8.C
+++ b/libgomp/testsuite/libgomp.c++/simd-8.C
@@ -1,6 +1,5 @@
// PR libgomp/58482
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd-9.C b/libgomp/testsuite/libgomp.c++/simd-9.C
index 3c567b31c3e..8f21bf2209a 100644
--- a/libgomp/testsuite/libgomp.c++/simd-9.C
+++ b/libgomp/testsuite/libgomp.c++/simd-9.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd10.C b/libgomp/testsuite/libgomp.c++/simd10.C
index 390e65ffea3..6fab68852a4 100644
--- a/libgomp/testsuite/libgomp.c++/simd10.C
+++ b/libgomp/testsuite/libgomp.c++/simd10.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd11.C b/libgomp/testsuite/libgomp.c++/simd11.C
index b9668685601..fde22034a60 100644
--- a/libgomp/testsuite/libgomp.c++/simd11.C
+++ b/libgomp/testsuite/libgomp.c++/simd11.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd12.C b/libgomp/testsuite/libgomp.c++/simd12.C
index ecfc912aeea..7596cad8571 100644
--- a/libgomp/testsuite/libgomp.c++/simd12.C
+++ b/libgomp/testsuite/libgomp.c++/simd12.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/simd13.C b/libgomp/testsuite/libgomp.c++/simd13.C
index f7496209680..67a0f70ff16 100644
--- a/libgomp/testsuite/libgomp.c++/simd13.C
+++ b/libgomp/testsuite/libgomp.c++/simd13.C
@@ -1,5 +1,4 @@
// { dg-do run }
-// { dg-options "-O2" }
// { dg-additional-options "-msse2" { target sse2_runtime } }
// { dg-additional-options "-mavx" { target avx_runtime } }
diff --git a/libgomp/testsuite/libgomp.c++/target-2.C b/libgomp/testsuite/libgomp.c++/target-2.C
index 83207cd51cd..35e910acc2e 100644
--- a/libgomp/testsuite/libgomp.c++/target-2.C
+++ b/libgomp/testsuite/libgomp.c++/target-2.C
@@ -1,4 +1,3 @@
-// { dg-options "-O2 -fopenmp" }
// { dg-additional-sources "target-2-aux.cc" }
extern "C" void abort (void);
diff --git a/libgomp/testsuite/libgomp.c++/udr-11.C b/libgomp/testsuite/libgomp.c++/udr-11.C
index 5d014467a9d..ee4bde319ad 100644
--- a/libgomp/testsuite/libgomp.c++/udr-11.C
+++ b/libgomp/testsuite/libgomp.c++/udr-11.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-1.C"
diff --git a/libgomp/testsuite/libgomp.c++/udr-12.C b/libgomp/testsuite/libgomp.c++/udr-12.C
index 58112eb6995..1d661baba56 100644
--- a/libgomp/testsuite/libgomp.c++/udr-12.C
+++ b/libgomp/testsuite/libgomp.c++/udr-12.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-2.C"
diff --git a/libgomp/testsuite/libgomp.c++/udr-13.C b/libgomp/testsuite/libgomp.c++/udr-13.C
index a9c8c600ca2..8e24ffd5007 100644
--- a/libgomp/testsuite/libgomp.c++/udr-13.C
+++ b/libgomp/testsuite/libgomp.c++/udr-13.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-3.C"
diff --git a/libgomp/testsuite/libgomp.c++/udr-14.C b/libgomp/testsuite/libgomp.c++/udr-14.C
index 6cb48293286..49fabcbbdfc 100644
--- a/libgomp/testsuite/libgomp.c++/udr-14.C
+++ b/libgomp/testsuite/libgomp.c++/udr-14.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-4.C"
diff --git a/libgomp/testsuite/libgomp.c++/udr-15.C b/libgomp/testsuite/libgomp.c++/udr-15.C
index d6aaf872029..e55101a0052 100644
--- a/libgomp/testsuite/libgomp.c++/udr-15.C
+++ b/libgomp/testsuite/libgomp.c++/udr-15.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-5.C"
diff --git a/libgomp/testsuite/libgomp.c++/udr-16.C b/libgomp/testsuite/libgomp.c++/udr-16.C
index acf4ff2028d..50fe6724bb2 100644
--- a/libgomp/testsuite/libgomp.c++/udr-16.C
+++ b/libgomp/testsuite/libgomp.c++/udr-16.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-6.C"
diff --git a/libgomp/testsuite/libgomp.c++/udr-17.C b/libgomp/testsuite/libgomp.c++/udr-17.C
index a5b62f8c67f..770b50d764d 100644
--- a/libgomp/testsuite/libgomp.c++/udr-17.C
+++ b/libgomp/testsuite/libgomp.c++/udr-17.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-7.C"
diff --git a/libgomp/testsuite/libgomp.c++/udr-18.C b/libgomp/testsuite/libgomp.c++/udr-18.C
index 5911e8e9a82..fb1f10c7508 100644
--- a/libgomp/testsuite/libgomp.c++/udr-18.C
+++ b/libgomp/testsuite/libgomp.c++/udr-18.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-8.C"
diff --git a/libgomp/testsuite/libgomp.c++/udr-19.C b/libgomp/testsuite/libgomp.c++/udr-19.C
index 801cab4342e..40d2eb9aeed 100644
--- a/libgomp/testsuite/libgomp.c++/udr-19.C
+++ b/libgomp/testsuite/libgomp.c++/udr-19.C
@@ -1,4 +1,4 @@
// { dg-do run }
-// { dg-options "-fopenmp -std=c++11" }
+// { dg-additional-options "-std=c++11" }
#include "udr-9.C"
diff --git a/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c
index cb5bf9cb8c5..7de1377cd56 100644
--- a/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c
+++ b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c
@@ -10,7 +10,7 @@
unsigned int *a;
unsigned int __attribute__((noclone,noinline))
-f (unsigned int n)
+f (unsigned int n, unsigned int *__restrict__ a)
{
int i;
unsigned int sum = 1;
@@ -32,7 +32,7 @@ main (void)
array[i] = i % 7;
a = &array[0];
- res = f (N);
+ res = f (N, a);
if (res != 11995)
abort ();
diff --git a/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-5.c b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-5.c
new file mode 100644
index 00000000000..d8d49b41aa5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-5.c
@@ -0,0 +1,75 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-parallelize-loops=2" } */
+
+/* Variable bound, vector addition, unsigned loop counter, unsigned bound. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 1000
+
+unsigned int a[N];
+unsigned int b[N];
+unsigned int c[N];
+
+void __attribute__((noclone,noinline))
+f (unsigned int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
+ unsigned int *__restrict__ c)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; ++i)
+ c[i] = a[i] + b[i];
+}
+
+static void __attribute__((noclone,noinline))
+init (void)
+{
+ int i, j;
+
+ /* Complexify loop to inhibit parloops. */
+ for (j = 0; j < 100; ++j)
+ for (i = 0; i < 10; i++)
+ {
+ int k = i + (10 * j);
+ a[k] = k;
+ b[k] = (k * 3) % 7;
+ c[k] = k * 2;
+ }
+}
+
+int
+main (void)
+{
+ int i;
+
+ init ();
+
+ f (N, a, b, c);
+
+ for (i = 0; i < N; i++)
+ {
+ unsigned int actual = c[i];
+ unsigned int expected = i + ((i * 3) % 7);
+ if (actual != expected)
+ abort ();
+ }
+
+ /* Test low iteration count case. */
+
+ init ();
+
+ f (10, a, b, c);
+
+ for (i = 0; i < N; i++)
+ {
+ unsigned int actual = c[i];
+ unsigned int expected = (i < 10
+ ? i + ((i * 3) % 7)
+ : i * 2);
+ if (actual != expected)
+ abort ();
+ }
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-6.c b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-6.c
new file mode 100644
index 00000000000..99c61c0c967
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-6.c
@@ -0,0 +1,75 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-parallelize-loops=2" } */
+
+/* Variable bound, vector addition, unsigned loop counter, signed bound. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 1000
+
+unsigned int a[N];
+unsigned int b[N];
+unsigned int c[N];
+
+void __attribute__((noclone,noinline))
+f (int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
+ unsigned int *__restrict__ c)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; ++i)
+ c[i] = a[i] + b[i];
+}
+
+static void __attribute__((noclone,noinline))
+init (void)
+{
+ int i, j;
+
+ /* Complexify loop to inhibit parloops. */
+ for (j = 0; j < 100; ++j)
+ for (i = 0; i < 10; i++)
+ {
+ int k = i + (10 * j);
+ a[k] = k;
+ b[k] = (k * 3) % 7;
+ c[k] = k * 2;
+ }
+}
+
+int
+main (void)
+{
+ int i;
+
+ init ();
+
+ f (N, a, b, c);
+
+ for (i = 0; i < N; i++)
+ {
+ unsigned int actual = c[i];
+ unsigned int expected = i + ((i * 3) % 7);
+ if (actual != expected)
+ abort ();
+ }
+
+ /* Test low iteration count case. */
+
+ init ();
+
+ f (10, a, b, c);
+
+ for (i = 0; i < N; i++)
+ {
+ unsigned int actual = c[i];
+ unsigned int expected = (i < 10
+ ? i + ((i * 3) % 7)
+ : i * 2);
+ if (actual != expected)
+ abort ();
+ }
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-7.c b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-7.c
new file mode 100644
index 00000000000..1f6e5e42ea4
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-7.c
@@ -0,0 +1,75 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-parallelize-loops=2" } */
+
+/* Variable bound, vector addition, signed loop counter, signed bound. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 1000
+
+unsigned int a[N];
+unsigned int b[N];
+unsigned int c[N];
+
+void __attribute__((noclone,noinline))
+f (int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
+ unsigned int *__restrict__ c)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ c[i] = a[i] + b[i];
+}
+
+static void __attribute__((noclone,noinline))
+init (void)
+{
+ int i, j;
+
+ /* Complexify loop to inhibit parloops. */
+ for (j = 0; j < 100; ++j)
+ for (i = 0; i < 10; i++)
+ {
+ int k = i + (10 * j);
+ a[k] = k;
+ b[k] = (k * 3) % 7;
+ c[k] = k * 2;
+ }
+}
+
+int
+main (void)
+{
+ int i;
+
+ init ();
+
+ f (N, a, b, c);
+
+ for (i = 0; i < N; i++)
+ {
+ unsigned int actual = c[i];
+ unsigned int expected = i + ((i * 3) % 7);
+ if (actual != expected)
+ abort ();
+ }
+
+ /* Test low iteration count case. */
+
+ init ();
+
+ f (10, a, b, c);
+
+ for (i = 0; i < N; i++)
+ {
+ unsigned int actual = c[i];
+ unsigned int expected = (i < 10
+ ? i + ((i * 3) % 7)
+ : i * 2);
+ if (actual != expected)
+ abort ();
+ }
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt.c b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt.c
index 1c32ea33f7b..d67a4f67ece 100644
--- a/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt.c
+++ b/libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt.c
@@ -1,7 +1,7 @@
/* { dg-do run } */
/* { dg-additional-options "-ftree-parallelize-loops=2" } */
-/* Variable bound, vector addition. */
+/* Variable bound, vector addition, signed loop counter, unsigned bound. */
#include <stdio.h>
#include <stdlib.h>
@@ -13,7 +13,8 @@ unsigned int b[N];
unsigned int c[N];
void __attribute__((noclone,noinline))
-f (unsigned int n)
+f (unsigned int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
+ unsigned int *__restrict__ c)
{
int i;
@@ -36,7 +37,7 @@ main (void)
c[k] = k * 2;
}
- f (N);
+ f (N, a, b, c);
for (i = 0; i < N; i++)
{
diff --git a/libgomp/testsuite/libgomp.oacc-c++/c++.exp b/libgomp/testsuite/libgomp.oacc-c++/c++.exp
index f486f9b97ba..80d135919cf 100644
--- a/libgomp/testsuite/libgomp.oacc-c++/c++.exp
+++ b/libgomp/testsuite/libgomp.oacc-c++/c++.exp
@@ -13,6 +13,11 @@ if [info exists lang_include_flags] then {
unset lang_include_flags
}
+# If a testcase doesn't have special options, use these.
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS "-O2"
+}
+
# Initialize dg.
dg-init
@@ -96,7 +101,7 @@ if { $lang_test_file_found } {
setenv ACC_DEVICE_TYPE $offload_target_openacc
- dg-runtest $tests "$tagopt" $libstdcxx_includes
+ dg-runtest $tests "$tagopt" "$libstdcxx_includes $DEFAULT_CFLAGS"
}
}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/collapse-3.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/collapse-3.c
index a5be7287d22..680042892e4 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/collapse-3.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/collapse-3.c
@@ -1,5 +1,4 @@
/* { dg-do run } */
-/* { dg-options "-O2" } */
#include <string.h>
#include <stdlib.h>
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 9e76cc4d27e..f159f786b7d 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,105 @@
+2015-06-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/Makefile.am (stamp-pdf-doxygen): Grep for LaTeX errors in log.
+ * doc/Makefile.in: Regenerate.
+
+ * include/bits/stl_pair.h: Replace class keyword with typename.
+
+2015-06-30 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ Implement N4387, "Improving pair and tuple", and LWG 2367.
+
+ * include/bits/stl_pair.h (_ConstructiblePair,
+ _ImplicitlyConvertiblePair, _MoveConstructiblePair,
+ _ImplicitlyMoveConvertiblePair): New.
+ (pair()): Constrain it.
+ (pair(const _T1&, const _T2&), pair(const pair<_U1, _U2>&),
+ pair(_U1&&, const _T2&), pair(const _T1&, _U2&&), pair(_U1&&, _U2&&),
+ pair(pair<_U1, _U2>&&)): Make conditionally explicit.
+ * include/std/tuple (_TC, tuple::_TC2, tuple::TCC, tuple::TMC): New.
+ (tuple()): Constrain it.
+ (tuple(const _UElements&...), tuple(_UElements&&...),
+ tuple(const tuple<_UElements...>&), tuple(tuple<_UElements...>&&),
+ tuple(allocator_arg_t, const _Alloc&, const _UElements&...),
+ tuple(allocator_arg_t, const _Alloc&, _UElements&&...),
+ tuple(allocator_arg_t, const _Alloc&, const tuple<_UElements...>&),
+ tuple(allocator_arg_t, const _Alloc&, tuple<_UElements...>&&),
+ tuple(const pair<_U1, _U2>&), tuple(pair<_U1, _U2>&&),
+ tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&),
+ tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&)): Make
+ conditionally explicit.
+ * include/experimental/functional (__boyer_moore_array_base): Name
+ array type explicitly instead of using an empty braced-init-list.
+ * testsuite/20_util/pair/cons/explicit_construct.cc: New.
+ * testsuite/20_util/pair/piecewise.cc: Use piecewise_construct.
+ * testsuite/20_util/pair/requirements/dr2367.cc: New.
+ * testsuite/20_util/tuple/cons/explicit_construct.cc: New.
+ * testsuite/20_util/tuple/requirements/dr2367.cc: New.
+
+2015-06-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * configure: Regenerate.
+
+2015-06-29 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/bits/stl_iterator_base_types.h (_Iter_base): Limit definition
+ to pre-C++11 mode.
+ * include/debug/functions.h
+ (__gnu_debug::__valid_range, __gnu_debug::__base): Move...
+ * include/debug/safe_iterator.h
+ (__gnu_debug::_Sequence_traits): New.
+ (__gnu_debug::__get_distance_from_begin): New.
+ (__gnu_debug::__get_distance_to_end): New.
+ (__gnu_debug::_Safe_iterator<>::_M_valid_range): Expose iterator range
+ distance information. Add optional check_dereferenceable parameter,
+ default true.
+ (__gnu_debug::_Distance_precision, __gnu_debug::__get_distance): Move
+ default definition...
+ (__gnu_debug::__get_distance): New overload for _Safe_iterator.
+ (__gnu_debug::__unsafe): Likewise.
+ * include/debug/helper_functions.h: ...here. New.
+ (__gnu_debug::__unsafe): New helper function to remove safe iterator
+ layer.
+ * include/debug/stl_iterator.h: New. Include latter.
+ * include/bits/stl_iterator.h: Include latter in debug mode.
+ * include/debug/stl_iterator.tcc: Adapt.
+ * include/debug/safe_local_iterator.h (__gnu_debug::__get_distance): Add
+ overload for _Safe_local_iterator.
+ (__gnu_debug::__unsafe): Likewise.
+ * include/debug/safe_local_iterator.tcc: Adapt.
+ * include/debug/macros.h (__glibcxx_check_valid_range2): New.
+ (__glibcxx_check_insert_range): Add _Dist parameter.
+ (__glibcxx_check_insert_range_after): Likewise.
+ (__glibcxx_check_string, __glibcxx_check_string_len): Implement using
+ _GLIBCXX_DEBUG_PEDASSERT.
+ * include/debug/deque (deque<>::assign): Remove iterator debug layer
+ when possible.
+ (deque<>::insert): Likewise.
+ * include/debug/forward_list (__glibcxx_check_valid_fl_range): New.
+ (forward_list<>::splice_after): Use latter.
+ (forward_list<>::assign): Remove iterator debug layer when possible.
+ (forward_list<>::insert_after): Likewise.
+ (__gnu_debug::_Sequence_traits<>): Partial specialization.
+ * include/debug/list (list<>::assign): Remove iterator debug layer when
+ possible.
+ (list<>::insert): Likewise.
+ [__gnu_debug::_Sequence_traits<>]: Partial specialization pre C++11 ABI.
+ * include/debug/map.h (map<>::insert): Remove iterator debug layer when
+ possible.
+ * include/debug/multimap.h (multimap<>::insert): Likewise.
+ * include/debug/set.h (set<>::insert): Likewise.
+ * include/debug/multiset.h (multiset<>::insert): Likewise.
+ * include/debug/string (basic_string<>::append, basic_string<>::assign,
+ basic_string<>::insert, basic_string<>::replace): Likewise.
+ * include/debug/unordered_map
+ (unordered_map<>::insert, unordered_multimap<>::insert): Likewise.
+ * include/debug/unordered_set
+ (unordered_set<>::insert, unordered_multiset<>insert): Likewise.
+ * include/debug/vector
+ (vector<>::assign, vector<>::insert): Likewise.
+ * include/Makefile.am: Add new debug headers.
+ * include/Makefile.in: Regenerate.
+
2015-06-26 Jonathan Wakely <jwakely@redhat.com>
* doc/xml/manual/intro.xml: Document LWG 2108 status.
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 3654b68f281..1b99c06c1ce 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -79216,7 +79216,7 @@ $as_echo_n "checking for sendfile that can copy files... " >&6; }
$as_echo_n "(cached) " >&6
else
case "${target_os}" in
- gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu | solaris*)
+ gnu* | linux* | solaris*)
if test x$gcc_no_link = xyes; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
diff --git a/libstdc++-v3/doc/Makefile.am b/libstdc++-v3/doc/Makefile.am
index d6ea2d1648d..d63cf17db8e 100644
--- a/libstdc++-v3/doc/Makefile.am
+++ b/libstdc++-v3/doc/Makefile.am
@@ -257,6 +257,7 @@ stamp-latex-doxygen: ${doxygen_outdir}/latex
# include asking a wizard to enlarge capacity. If this is the case,
# find texmf.cnf and add a zero for pool_size, string_vacancies,
# max_strings, and pool_free values.
+# Errors like "File `foo.sty' not found" mean a TeX package is missing.
stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf
-(cd ${doxygen_outdir}/latex && $(MAKE) -i pdf;)
echo "Generating doxygen pdf file...";
@@ -265,6 +266,7 @@ stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf
echo ":: PDF file is ${api_pdf}"; \
else \
echo "... error"; \
+ grep -F 'LaTeX Error' ${doxygen_outdir}/latex/refman.log; \
exit 12; \
fi
$(STAMP) stamp-pdf-doxygen
diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in
index 4690fad8ac6..798a9a3ae37 100644
--- a/libstdc++-v3/doc/Makefile.in
+++ b/libstdc++-v3/doc/Makefile.in
@@ -891,6 +891,7 @@ stamp-latex-doxygen: ${doxygen_outdir}/latex
# include asking a wizard to enlarge capacity. If this is the case,
# find texmf.cnf and add a zero for pool_size, string_vacancies,
# max_strings, and pool_free values.
+# Errors like "File `foo.sty' not found" mean a TeX package is missing.
stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf
-(cd ${doxygen_outdir}/latex && $(MAKE) -i pdf;)
echo "Generating doxygen pdf file...";
@@ -899,6 +900,7 @@ stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf
echo ":: PDF file is ${api_pdf}"; \
else \
echo "... error"; \
+ grep -F 'LaTeX Error' ${doxygen_outdir}/latex/refman.log; \
exit 12; \
fi
$(STAMP) stamp-pdf-doxygen
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 927418ed8b0..05be8ad1b84 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -766,6 +766,7 @@ debug_headers = \
${debug_srcdir}/formatter.h \
${debug_srcdir}/forward_list \
${debug_srcdir}/functions.h \
+ ${debug_srcdir}/helper_functions.h \
${debug_srcdir}/list \
${debug_srcdir}/map \
${debug_srcdir}/macros.h \
@@ -785,6 +786,7 @@ debug_headers = \
${debug_srcdir}/safe_unordered_container.tcc \
${debug_srcdir}/set \
${debug_srcdir}/set.h \
+ ${debug_srcdir}/stl_iterator.h \
${debug_srcdir}/string \
${debug_srcdir}/unordered_map \
${debug_srcdir}/unordered_set \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 0674d8ca976..bab83b40018 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -1047,6 +1047,7 @@ debug_headers = \
${debug_srcdir}/formatter.h \
${debug_srcdir}/forward_list \
${debug_srcdir}/functions.h \
+ ${debug_srcdir}/helper_functions.h \
${debug_srcdir}/list \
${debug_srcdir}/map \
${debug_srcdir}/macros.h \
@@ -1066,6 +1067,7 @@ debug_headers = \
${debug_srcdir}/safe_unordered_container.tcc \
${debug_srcdir}/set \
${debug_srcdir}/set.h \
+ ${debug_srcdir}/stl_iterator.h \
${debug_srcdir}/string \
${debug_srcdir}/unordered_map \
${debug_srcdir}/unordered_set \
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 58b9aabf2e6..1060433d0bd 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -1246,4 +1246,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter)
#endif // C++11
+#ifdef _GLIBCXX_DEBUG
+# include <debug/stl_iterator.h>
+#endif
+
#endif
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h
index 83e6444ab1c..eba9e398be7 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_types.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h
@@ -206,6 +206,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//@}
+#if __cplusplus < 201103L
// If _Iterator has a base returns it otherwise _Iterator is returned
// untouched
template<typename _Iterator, bool _HasBase>
@@ -223,6 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static iterator_type _S_base(_Iterator __it)
{ return __it.base(); }
};
+#endif
#if __cplusplus >= 201103L
template<typename _InIter>
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 490b00565a0..a5a7898f2b7 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -84,6 +84,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<std::size_t...>
struct _Index_tuple;
+
+ // Concept utility functions, reused in conditionally-explicit
+ // constructors.
+ template <typename _T1, typename _T2, typename _U1, typename _U2>
+ constexpr bool _ConstructiblePair()
+ {
+ return __and_<is_constructible<_T1, const _U1&>,
+ is_constructible<_T2, const _U2&>>::value;
+ }
+
+ template <typename _T1, typename _T2, typename _U1, typename _U2>
+ constexpr bool _ImplicitlyConvertiblePair()
+ {
+ return __and_<is_convertible<const _U1&, _T1>,
+ is_convertible<const _U2&, _T2>>::value;
+ }
+
+ template <typename _T1, typename _T2, typename _U1, typename _U2>
+ constexpr bool _MoveConstructiblePair()
+ {
+ return __and_<is_constructible<_T1, _U1&&>,
+ is_constructible<_T2, _U2&&>>::value;
+ }
+
+ template <typename _T1, typename _T2, typename _U1, typename _U2>
+ constexpr bool _ImplicitlyMoveConvertiblePair()
+ {
+ return __and_<is_convertible<_U1&&, _T1>,
+ is_convertible<_U2&&, _T2>>::value;
+ }
+
+
#endif
/**
@@ -92,7 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @tparam _T1 Type of first object.
* @tparam _T2 Type of second object.
*/
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
struct pair
{
typedef _T1 first_type; /// @c first_type is the first bound type
@@ -105,52 +137,136 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 265. std::pair::pair() effects overly restrictive
/** The default constructor creates @c first and @c second using their
* respective default constructors. */
+#if __cplusplus >= 201103L
+ template <typename _U1 = _T1,
+ typename _U2 = _T2,
+ typename enable_if<__and_<
+ is_default_constructible<_U1>,
+ is_default_constructible<_U2>>
+ ::value, bool>::type = true>
+#endif
_GLIBCXX_CONSTEXPR pair()
: first(), second() { }
/** Two objects may be passed to a @c pair constructor to be copied. */
- _GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b)
+#if __cplusplus < 201103L
+ pair(const _T1& __a, const _T2& __b)
+ : first(__a), second(__b) { }
+#else
+ template<typename _U1 = _T1, typename _U2=_T2, typename
+ enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+ && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+ bool>::type=true>
+ constexpr pair(const _T1& __a, const _T2& __b)
: first(__a), second(__b) { }
+ template<typename _U1 = _T1, typename _U2=_T2, typename
+ enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+ && !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+ bool>::type=false>
+ explicit constexpr pair(const _T1& __a, const _T2& __b)
+ : first(__a), second(__b) { }
+#endif
+
/** There is also a templated copy ctor for the @c pair class itself. */
#if __cplusplus < 201103L
- template<class _U1, class _U2>
+ template<typename _U1, typename _U2>
pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
#else
- template<class _U1, class _U2, class = typename
- enable_if<__and_<is_convertible<const _U1&, _T1>,
- is_convertible<const _U2&, _T2>>::value>::type>
- constexpr pair(const pair<_U1, _U2>& __p)
+ template<typename _U1, typename _U2, typename
+ enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+ && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+ bool>::type=true>
+ constexpr pair(const pair<_U1, _U2>& __p)
+ : first(__p.first), second(__p.second) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+ && !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+ bool>::type=false>
+ explicit constexpr pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
constexpr pair(const pair&) = default;
constexpr pair(pair&&) = default;
// DR 811.
- template<class _U1, class = typename
- enable_if<is_convertible<_U1, _T1>::value>::type>
- constexpr pair(_U1&& __x, const _T2& __y)
- : first(std::forward<_U1>(__x)), second(__y) { }
-
- template<class _U2, class = typename
- enable_if<is_convertible<_U2, _T2>::value>::type>
- constexpr pair(const _T1& __x, _U2&& __y)
- : first(__x), second(std::forward<_U2>(__y)) { }
-
- template<class _U1, class _U2, class = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ template<typename _U1, typename
+ enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>()
+ && _MoveConstructiblePair<_T1, _T2, _U1, _T2>()
+ && _ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>()
+ && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _T2>(),
+ bool>::type=true>
+ constexpr pair(_U1&& __x, const _T2& __y)
+ : first(std::forward<_U1>(__x)), second(__y) { }
+
+ template<typename _U1, typename
+ enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>()
+ && _MoveConstructiblePair<_T1, _T2, _U1, _T2>()
+ && (!_ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>()
+ || !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _T2>()),
+ bool>::type=false>
+ explicit constexpr pair(_U1&& __x, const _T2& __y)
+ : first(std::forward<_U1>(__x)), second(__y) { }
+
+ template<typename _U2, typename
+ enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>()
+ && _MoveConstructiblePair<_T1, _T2, _T1, _U2>()
+ && _ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>()
+ && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _T1, _U2>(),
+ bool>::type=true>
+ constexpr pair(const _T1& __x, _U2&& __y)
+ : first(__x), second(std::forward<_U2>(__y)) { }
+
+ template<typename _U2, typename
+ enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>()
+ && _MoveConstructiblePair<_T1, _T2, _T1, _U2>()
+ && (!_ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>()
+ || !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _T1, _U2>()),
+ bool>::type=false>
+ explicit pair(const _T1& __x, _U2&& __y)
+ : first(__x), second(std::forward<_U2>(__y)) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+ && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _U2>(),
+ bool>::type=true>
constexpr pair(_U1&& __x, _U2&& __y)
: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
- template<class _U1, class _U2, class = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+ && !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _U2>(),
+ bool>::type=false>
+ explicit constexpr pair(_U1&& __x, _U2&& __y)
+ : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
+
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+ && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _U2>(),
+ bool>::type=true>
constexpr pair(pair<_U1, _U2>&& __p)
: first(std::forward<_U1>(__p.first)),
second(std::forward<_U2>(__p.second)) { }
+ template<typename _U1, typename _U2, typename
+ enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+ && !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _U2>(),
+ bool>::type=false>
+ explicit constexpr pair(pair<_U1, _U2>&& __p)
+ : first(std::forward<_U1>(__p.first)),
+ second(std::forward<_U2>(__p.second)) { }
+
template<typename... _Args1, typename... _Args2>
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
@@ -172,7 +288,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
- template<class _U1, class _U2>
+ template<typename _U1, typename _U2>
pair&
operator=(const pair<_U1, _U2>& __p)
{
@@ -181,7 +297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
- template<class _U1, class _U2>
+ template<typename _U1, typename _U2>
pair&
operator=(pair<_U1, _U2>&& __p)
{
@@ -209,38 +325,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
/// Two pairs of the same type are equal iff their members are equal.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __x.first == __y.first && __x.second == __y.second; }
/// <http://gcc.gnu.org/onlinedocs/libstdc++/manual/utilities.html>
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __x.first < __y.first
|| (!(__y.first < __x.first) && __x.second < __y.second); }
/// Uses @c operator== to find the result.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__x == __y); }
/// Uses @c operator< to find the result.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __y < __x; }
/// Uses @c operator< to find the result.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__y < __x); }
/// Uses @c operator< to find the result.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__x < __y); }
@@ -249,7 +365,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// See std::pair::swap().
// Note: no std::swap overloads in C++03 mode, this has performance
// implications, see, eg, libstdc++/38466.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline void
swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
noexcept(noexcept(__x.swap(__y)))
@@ -270,7 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 181. make_pair() unintended behavior
#if __cplusplus >= 201103L
// NB: DR 706.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
constexpr pair<typename __decay_and_strip<_T1>::__type,
typename __decay_and_strip<_T2>::__type>
make_pair(_T1&& __x, _T2&& __y)
@@ -281,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));
}
#else
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline pair<_T1, _T2>
make_pair(_T1 __x, _T2 __y)
{ return pair<_T1, _T2>(__x, __y); }
diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
index fffc5e4ab63..7d15e33606b 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -169,9 +169,14 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
}
@@ -460,10 +465,16 @@ namespace __debug
insert(const_iterator __position,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
- _Base_iterator __res = _Base::insert(__position.base(),
- __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+ _Base_iterator __res;
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ __res = _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ __res = _Base::insert(__position.base(), __first, __last);
+
this->_M_invalidate_all();
return iterator(__res, this);
}
@@ -473,9 +484,16 @@ namespace __debug
insert(iterator __position,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
- _Base::insert(__position.base(), __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__position.base(), __first, __last);
+
this->_M_invalidate_all();
}
#endif
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index 2b42a3f8d29..df35bc29cf5 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -36,6 +36,13 @@
#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
+// Special validity check for forward_list ranges.
+#define __glibcxx_check_valid_fl_range(_First,_Last,_Dist) \
+_GLIBCXX_DEBUG_VERIFY(_First._M_valid_range(_Last, _Dist, false), \
+ _M_message(__gnu_debug::__msg_valid_range) \
+ ._M_iterator(_First, #_First) \
+ ._M_iterator(_Last, #_Last))
+
namespace __gnu_debug
{
/// Special iterators swap and invalidation for forward_list because of the
@@ -269,9 +276,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
}
@@ -401,11 +414,19 @@ namespace __debug
insert_after(const_iterator __pos,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range_after(__pos, __first, __last);
- return iterator(_Base::insert_after(__pos.base(),
- __gnu_debug::__base(__first),
- __gnu_debug::__base(__last)),
- this);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range_after(__pos, __first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ return
+ {
+ _Base::insert_after(__pos.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last)),
+ this
+ };
+ else
+ return { _Base::insert_after(__pos.base(), __first, __last), this };
}
iterator
@@ -580,9 +601,10 @@ namespace __debug
splice_after(const_iterator __pos, forward_list&& __list,
const_iterator __before, const_iterator __last)
{
+ typename __gnu_debug::_Distance_traits<const_iterator>::__type __dist;
auto __listptr = std::__addressof(__list);
__glibcxx_check_insert_after(__pos);
- __glibcxx_check_valid_range(__before, __last);
+ __glibcxx_check_valid_fl_range(__before, __last, __dist);
_GLIBCXX_DEBUG_VERIFY(__before._M_attached_to(__listptr),
_M_message(__gnu_debug::__msg_splice_other)
._M_sequence(__list, "list")
@@ -801,7 +823,7 @@ namespace __debug
namespace __gnu_debug
{
- template<class _Tp, class _Alloc>
+ template<typename _Tp, typename _Alloc>
struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
{
typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
@@ -820,6 +842,19 @@ namespace __gnu_debug
{ return _S_Is(__it); }
};
+ template<typename _Tp, typename _Alloc>
+ struct _Sequence_traits<std::__debug::forward_list<_Tp, _Alloc> >
+ {
+ typedef typename std::__debug::forward_list<_Tp, _Alloc>::iterator _It;
+
+ static typename _Distance_traits<_It>::__type
+ _S_size(const std::__debug::forward_list<_Tp, _Alloc>& __seq)
+ {
+ return __seq.empty()
+ ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
+ }
+ };
+
#ifndef _GLIBCXX_DEBUG_PEDANTIC
template<class _Tp, class _Alloc>
struct _Insert_range_from_self_is_safe<
diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h
index bf60ccc23c6..7f0659f5b25 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -29,11 +29,6 @@
#ifndef _GLIBCXX_DEBUG_FUNCTIONS_H
#define _GLIBCXX_DEBUG_FUNCTIONS_H 1
-#include <bits/c++config.h>
-#include <bits/stl_iterator_base_types.h> // for iterator_traits,
- // categories and _Iter_base
-#include <bits/cpp_type_traits.h> // for __is_integer
-
#include <bits/move.h> // for __addressof
#include <bits/stl_function.h> // for less
#if __cplusplus >= 201103L
@@ -41,6 +36,7 @@
// conditional.
#endif
+#include <debug/helper_functions.h>
#include <debug/formatter.h>
namespace __gnu_debug
@@ -85,58 +81,6 @@ namespace __gnu_debug
__check_dereferenceable(const _Tp* __ptr)
{ return __ptr; }
- /** If the distance between two random access iterators is
- * nonnegative, assume the range is valid.
- */
- template<typename _RandomAccessIterator>
- inline bool
- __valid_range_aux2(const _RandomAccessIterator& __first,
- const _RandomAccessIterator& __last,
- std::random_access_iterator_tag)
- { return __last - __first >= 0; }
-
- /** Can't test for a valid range with input iterators, because
- * iteration may be destructive. So we just assume that the range
- * is valid.
- */
- template<typename _InputIterator>
- inline bool
- __valid_range_aux2(const _InputIterator&, const _InputIterator&,
- std::input_iterator_tag)
- { return true; }
-
- /** We say that integral types for a valid range, and defer to other
- * routines to realize what to do with integral types instead of
- * iterators.
- */
- template<typename _Integral>
- inline bool
- __valid_range_aux(const _Integral&, const _Integral&, std::__true_type)
- { return true; }
-
- /** We have iterators, so figure out what kind of iterators that are
- * to see if we can check the range ahead of time.
- */
- template<typename _InputIterator>
- inline bool
- __valid_range_aux(const _InputIterator& __first,
- const _InputIterator& __last, std::__false_type)
- { return __valid_range_aux2(__first, __last,
- std::__iterator_category(__first)); }
-
- /** Don't know what these iterators are, or if they are even
- * iterators (we may get an integral type for InputIterator), so
- * see if they are integral and pass them on to the next phase
- * otherwise.
- */
- template<typename _InputIterator>
- inline bool
- __valid_range(const _InputIterator& __first, const _InputIterator& __last)
- {
- typedef typename std::__is_integer<_InputIterator>::__type _Integral;
- return __valid_range_aux(__first, __last, _Integral());
- }
-
/* Checks that [first, last) is a valid range, and then returns
* __first. This routine is useful when we can't use a separate
* assertion statement because, e.g., we are in a constructor.
@@ -500,29 +444,6 @@ namespace __gnu_debug
return __first == __last;
}
- // Helper struct to detect random access safe iterators.
- template<typename _Iterator>
- struct __is_safe_random_iterator
- {
- enum { __value = 0 };
- typedef std::__false_type __type;
- };
-
- template<typename _Iterator>
- struct _Siter_base
- : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
- { };
-
- /** Helper function to extract base iterator of random access safe iterator
- in order to reduce performance impact of debug mode. Limited to random
- access iterator because it is the only category for which it is possible
- to check for correct iterators order in the __valid_range function
- thanks to the < operator.
- */
- template<typename _Iterator>
- inline typename _Siter_base<_Iterator>::iterator_type
- __base(_Iterator __it)
- { return _Siter_base<_Iterator>::_S_base(__it); }
} // namespace __gnu_debug
#endif
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
new file mode 100644
index 00000000000..a2db00d29cc
--- /dev/null
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -0,0 +1,210 @@
+// Debugging support implementation -*- C++ -*-
+
+// Copyright (C) 2003-2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file debug/helper_functions.h
+ * This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H
+#define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1
+
+#include <bits/stl_iterator_base_types.h> // for iterator_traits,
+ // categories and _Iter_base
+#include <bits/cpp_type_traits.h> // for __is_integer
+
+#include <bits/stl_pair.h> // for pair
+
+namespace __gnu_debug
+{
+ /** The precision to which we can calculate the distance between
+ * two iterators.
+ */
+ enum _Distance_precision
+ {
+ __dp_none, // Not even an iterator type
+ __dp_equality, //< Can compare iterator equality, only
+ __dp_sign, //< Can determine equality and ordering
+ __dp_exact //< Can determine distance precisely
+ };
+
+ template<typename _Iterator,
+ typename = typename std::__is_integer<_Iterator>::__type>
+ struct _Distance_traits
+ {
+ private:
+ typedef
+ typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
+
+ template<typename _DiffType,
+ typename = typename std::__is_void<_DiffType>::__type>
+ struct _DiffTraits
+ { typedef _DiffType __type; };
+
+ template<typename _DiffType>
+ struct _DiffTraits<_DiffType, std::__true_type>
+ { typedef std::ptrdiff_t __type; };
+
+ typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
+
+ public:
+ typedef std::pair<_DiffType, _Distance_precision> __type;
+ };
+
+ template<typename _Integral>
+ struct _Distance_traits<_Integral, std::__true_type>
+ { typedef std::pair<std::ptrdiff_t, _Distance_precision> __type; };
+
+ /** Determine the distance between two iterators with some known
+ * precision.
+ */
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
+ std::random_access_iterator_tag)
+ { return std::make_pair(__rhs - __lhs, __dp_exact); }
+
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
+ std::input_iterator_tag)
+ {
+ if (__lhs == __rhs)
+ return std::make_pair(0, __dp_exact);
+
+ return std::make_pair(1, __dp_equality);
+ }
+
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
+ { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
+
+ /** We say that integral types for a valid range, and defer to other
+ * routines to realize what to do with integral types instead of
+ * iterators.
+ */
+ template<typename _Integral>
+ inline bool
+ __valid_range_aux(const _Integral&, const _Integral&,
+ typename _Distance_traits<_Integral>::__type& __dist,
+ std::__true_type)
+ {
+ __dist = std::make_pair(0, __dp_none);
+ return true;
+ }
+
+ /** We have iterators, so figure out what kind of iterators that are
+ * to see if we can check the range ahead of time.
+ */
+ template<typename _InputIterator>
+ inline bool
+ __valid_range_aux(const _InputIterator& __first,
+ const _InputIterator& __last,
+ typename _Distance_traits<_InputIterator>::__type& __dist,
+ std::__false_type)
+ {
+ __dist = __get_distance(__first, __last);
+ switch (__dist.second)
+ {
+ case __dp_none:
+ break;
+ case __dp_equality:
+ if (__dist.first == 0)
+ return true;
+ break;
+ case __dp_sign:
+ case __dp_exact:
+ return __dist.first >= 0;
+ }
+
+ return true;
+ }
+
+ /** Don't know what these iterators are, or if they are even
+ * iterators (we may get an integral type for InputIterator), so
+ * see if they are integral and pass them on to the next phase
+ * otherwise.
+ */
+ template<typename _InputIterator>
+ inline bool
+ __valid_range(const _InputIterator& __first, const _InputIterator& __last,
+ typename _Distance_traits<_InputIterator>::__type& __dist)
+ {
+ typedef typename std::__is_integer<_InputIterator>::__type _Integral;
+ return __valid_range_aux(__first, __last, __dist, _Integral());
+ }
+
+ template<typename _InputIterator>
+ inline bool
+ __valid_range(const _InputIterator& __first, const _InputIterator& __last)
+ {
+ typename _Distance_traits<_InputIterator>::__type __dist;
+ return __valid_range(__first, __last, __dist);
+ }
+
+#if __cplusplus < 201103L
+ // Helper struct to detect random access safe iterators.
+ template<typename _Iterator>
+ struct __is_safe_random_iterator
+ {
+ enum { __value = 0 };
+ typedef std::__false_type __type;
+ };
+
+ template<typename _Iterator>
+ struct _Siter_base
+ : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
+ { };
+
+ /** Helper function to extract base iterator of random access safe iterator
+ in order to reduce performance impact of debug mode. Limited to random
+ access iterator because it is the only category for which it is possible
+ to check for correct iterators order in the __valid_range function
+ thanks to the < operator.
+ */
+ template<typename _Iterator>
+ inline typename _Siter_base<_Iterator>::iterator_type
+ __base(_Iterator __it)
+ { return _Siter_base<_Iterator>::_S_base(__it); }
+#else
+ template<typename _Iterator>
+ inline _Iterator
+ __base(_Iterator __it)
+ { return __it; }
+#endif
+
+#if __cplusplus < 201103L
+ template<typename _Iterator>
+ struct _Unsafe_type
+ { typedef _Iterator _Type; };
+#endif
+
+ /* Remove debug mode safe iterator layer, if any. */
+ template<typename _Iterator>
+ inline _Iterator
+ __unsafe(_Iterator __it)
+ { return __it; }
+}
+
+#endif
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index 12ac53c4675..0f3f1a0e241 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -177,9 +177,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
}
@@ -441,11 +447,18 @@ namespace __debug
insert(const_iterator __position, _InputIterator __first,
_InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
- return iterator(_Base::insert(__position.base(),
- __gnu_debug::__base(__first),
- __gnu_debug::__base(__last)),
- this);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ return
+ {
+ _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last)),
+ this
+ };
+ else
+ return { _Base::insert(__position.base(), __first, __last), this };
}
#else
template<class _InputIterator>
@@ -453,9 +466,14 @@ namespace __debug
insert(iterator __position, _InputIterator __first,
_InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
- _Base::insert(__position.base(), __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__position.base(), __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__position.base(), __first, __last);
}
#endif
@@ -795,13 +813,29 @@ namespace __debug
} // namespace __debug
} // namespace std
-#ifndef _GLIBCXX_DEBUG_PEDANTIC
namespace __gnu_debug
{
+#ifndef _GLIBCXX_USE_CXX11_ABI
+ // If not using C++11 list::size() is not in O(1) so we do not use it.
+ template<typename _Tp, typename _Alloc>
+ struct _Sequence_traits<std::__debug::list<_Tp, _Alloc> >
+ {
+ typedef typename std::__debug::list<_Tp, _Alloc>::iterator _It;
+
+ static typename _Distance_traits<_It>::__type
+ _S_size(const std::__debug::list<_Tp, _Alloc>& __seq)
+ {
+ return __seq.empty()
+ ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
+ }
+ };
+#endif
+
+#ifndef _GLIBCXX_DEBUG_PEDANTIC
template<class _Tp, class _Alloc>
struct _Insert_range_from_self_is_safe<std::__debug::list<_Tp, _Alloc> >
{ enum { __value = 1 }; };
-}
#endif
+}
#endif
diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h
index f796e718770..a4c2649c843 100644
--- a/libstdc++-v3/include/debug/macros.h
+++ b/libstdc++-v3/include/debug/macros.h
@@ -56,6 +56,12 @@ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last), \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
+#define __glibcxx_check_valid_range2(_First,_Last,_Dist) \
+_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last, _Dist), \
+ _M_message(__gnu_debug::__msg_valid_range) \
+ ._M_iterator(_First, #_First) \
+ ._M_iterator(_Last, #_Last))
+
// Verify that [_First, _Last) forms a non-empty iterator range.
#define __glibcxx_check_non_empty_range(_First,_Last) \
_GLIBCXX_DEBUG_VERIFY(_First != _Last, \
@@ -104,8 +110,8 @@ _GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(), \
* Note that this macro is only valid when the container is a
* _Safe_sequence and the _Position iterator is a _Safe_iterator.
*/
-#define __glibcxx_check_insert_range(_Position,_First,_Last) \
-__glibcxx_check_valid_range(_First,_Last); \
+#define __glibcxx_check_insert_range(_Position,_First,_Last,_Dist) \
+__glibcxx_check_valid_range2(_First,_Last,_Dist); \
__glibcxx_check_insert(_Position); \
_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
_M_message(__gnu_debug::__msg_insert_range_from_self)\
@@ -123,8 +129,8 @@ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
* Note that this macro is only valid when the container is a
* _Safe_sequence and the _Position iterator is a _Safe_iterator.
*/
-#define __glibcxx_check_insert_range_after(_Position,_First,_Last) \
-__glibcxx_check_valid_range(_First,_Last); \
+#define __glibcxx_check_insert_range_after(_Position,_First,_Last,_Dist)\
+ __glibcxx_check_valid_range2(_First,_Last,_Dist); \
__glibcxx_check_insert_after(_Position); \
_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
_M_message(__gnu_debug::__msg_insert_range_from_self)\
@@ -352,13 +358,8 @@ _GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \
_M_message(__gnu_debug::__msg_equal_allocs) \
._M_sequence(_This, "this"))
-#ifdef _GLIBCXX_DEBUG_PEDANTIC
-# define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0)
-# define __glibcxx_check_string_len(_String,_Len) \
- _GLIBCXX_DEBUG_ASSERT(_String != 0 || _Len == 0)
-#else
-# define __glibcxx_check_string(_String)
-# define __glibcxx_check_string_len(_String,_Len)
-#endif
+#define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_PEDASSERT(_String != 0)
+#define __glibcxx_check_string_len(_String,_Len) \
+ _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0)
#endif
diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h
index 688fb99d499..9bda8eba1da 100644
--- a/libstdc++-v3/include/debug/map.h
+++ b/libstdc++-v3/include/debug/map.h
@@ -307,9 +307,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h
index e2c806131f0..b9b0a74c94e 100644
--- a/libstdc++-v3/include/debug/multimap.h
+++ b/libstdc++-v3/include/debug/multimap.h
@@ -286,9 +286,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h
index b4d738f4bec..f1f6e2c576a 100644
--- a/libstdc++-v3/include/debug/multiset.h
+++ b/libstdc++-v3/include/debug/multiset.h
@@ -271,9 +271,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index 9f2dcd1e238..a8bee214e36 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -41,7 +41,7 @@ namespace __gnu_debug
/** Helper struct to deal with sequence offering a before_begin
* iterator.
**/
- template <typename _Sequence>
+ template<typename _Sequence>
struct _BeforeBeginHelper
{
template<typename _Iterator>
@@ -55,38 +55,16 @@ namespace __gnu_debug
{ return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
};
- /** The precision to which we can calculate the distance between
- * two iterators.
- */
- enum _Distance_precision
+ /** Sequence traits giving the size of a container if possible. */
+ template<typename _Sequence>
+ struct _Sequence_traits
{
- __dp_equality, //< Can compare iterator equality, only
- __dp_sign, //< Can determine equality and ordering
- __dp_exact //< Can determine distance precisely
- };
-
- /** Determine the distance between two iterators with some known
- * precision.
- */
- template<typename _Iterator>
- inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
- _Distance_precision>
- __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
- std::random_access_iterator_tag)
- { return std::make_pair(__rhs - __lhs, __dp_exact); }
+ typedef _Distance_traits<typename _Sequence::iterator> _DistTraits;
- template<typename _Iterator>
- inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
- _Distance_precision>
- __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
- std::forward_iterator_tag)
- { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
-
- template<typename _Iterator>
- inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
- _Distance_precision>
- __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
- { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
+ static typename _DistTraits::__type
+ _S_size(const _Sequence& __seq)
+ { return std::make_pair(__seq.size(), __dp_exact); }
+ };
/** \brief Safe iterator wrapper.
*
@@ -476,7 +454,9 @@ namespace __gnu_debug
// Is the iterator range [*this, __rhs) valid?
bool
- _M_valid_range(const _Safe_iterator& __rhs) const;
+ _M_valid_range(const _Safe_iterator& __rhs,
+ std::pair<difference_type, _Distance_precision>& __dist,
+ bool __check_dereferenceable = true) const;
// The sequence this iterator references.
typename
@@ -768,15 +748,157 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first,
- const _Safe_iterator<_Iterator, _Sequence>& __last)
- { return __first._M_valid_range(__last); }
+ const _Safe_iterator<_Iterator, _Sequence>& __last,
+ typename _Distance_traits<_Iterator>::__type& __dist)
+ { return __first._M_valid_range(__last, __dist); }
+
+ /** Safe iterators can help to get better distance knowledge. */
+ template<typename _Iterator, typename _Sequence>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Safe_iterator<_Iterator, _Sequence>& __first,
+ const _Safe_iterator<_Iterator, _Sequence>& __last,
+ std::random_access_iterator_tag)
+ { return std::make_pair(__last.base() - __first.base(), __dp_exact); }
+
+ template<typename _Iterator, typename _Sequence>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Safe_iterator<_Iterator, _Sequence>& __first,
+ const _Safe_iterator<_Iterator, _Sequence>& __last,
+ std::input_iterator_tag)
+ {
+ typedef typename _Distance_traits<_Iterator>::__type _Diff;
+ typedef _Sequence_traits<_Sequence> _SeqTraits;
+
+ if (__first.base() == __last.base())
+ return std::make_pair(0, __dp_exact);
+
+ if (__first._M_is_before_begin())
+ {
+ if (__last._M_is_begin())
+ return std::make_pair(1, __dp_exact);
+
+ return std::make_pair(1, __dp_sign);
+ }
+
+ if (__first._M_is_begin())
+ {
+ if (__last._M_is_before_begin())
+ return std::make_pair(-1, __dp_exact);
+
+ if (__last._M_is_end())
+ return _SeqTraits::_S_size(*__first._M_get_sequence());
+
+ return std::make_pair(1, __dp_sign);
+ }
+
+ if (__first._M_is_end())
+ {
+ if (__last._M_is_before_begin())
+ return std::make_pair(-1, __dp_exact);
+
+ if (__last._M_is_begin())
+ {
+ _Diff __diff = _SeqTraits::_S_size(*__first._M_get_sequence());
+ return std::make_pair(-__diff.first, __diff.second);
+ }
+
+ return std::make_pair(-1, __dp_sign);
+ }
+
+ if (__last._M_is_before_begin() || __last._M_is_begin())
+ return std::make_pair(-1, __dp_sign);
+
+ if (__last._M_is_end())
+ return std::make_pair(1, __dp_sign);
+
+ return std::make_pair(1, __dp_equality);
+ }
+
+ // Get distance from sequence begin to specified iterator.
+ template<typename _Iterator, typename _Sequence>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance_from_begin(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ {
+ typedef _Sequence_traits<_Sequence> _SeqTraits;
+
+ // No need to consider before_begin as this function is only used in
+ // _M_can_advance which won't be used for forward_list iterators.
+ if (__it._M_is_begin())
+ return std::make_pair(0, __dp_exact);
+
+ if (__it._M_is_end())
+ return _SeqTraits::_S_size(*__it._M_get_sequence());
+
+ typename _Distance_traits<_Iterator>::__type __res
+ = __get_distance(__it._M_get_sequence()->_M_base().begin(), __it.base());
+
+ if (__res.second == __dp_equality)
+ return std::make_pair(1, __dp_sign);
+
+ return __res;
+ }
+
+ // Get distance from specified iterator to sequence end.
+ template<typename _Iterator, typename _Sequence>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance_to_end(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ {
+ typedef _Sequence_traits<_Sequence> _SeqTraits;
+
+ // No need to consider before_begin as this function is only used in
+ // _M_can_advance which won't be used for forward_list iterators.
+ if (__it._M_is_begin())
+ return _SeqTraits::_S_size(*__it._M_get_sequence());
+
+ if (__it._M_is_end())
+ return std::make_pair(0, __dp_exact);
+ typename _Distance_traits<_Iterator>::__type __res
+ = __get_distance(__it.base(), __it._M_get_sequence()->_M_base().end());
+
+ if (__res.second == __dp_equality)
+ return std::make_pair(1, __dp_sign);
+
+ return __res;
+ }
+
+#if __cplusplus < 201103L
template<typename _Iterator, typename _Sequence>
struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
: std::__are_same<std::random_access_iterator_tag,
typename std::iterator_traits<_Iterator>::
iterator_category>
{ };
+#else
+ template<typename _Iterator, typename _Sequence>
+ _Iterator
+ __base(const _Safe_iterator<_Iterator, _Sequence>& __it,
+ std::random_access_iterator_tag)
+ { return __it.base(); }
+
+ template<typename _Iterator, typename _Sequence>
+ const _Safe_iterator<_Iterator, _Sequence>&
+ __base(const _Safe_iterator<_Iterator, _Sequence>& __it,
+ std::input_iterator_tag)
+ { return __it; }
+
+ template<typename _Iterator, typename _Sequence>
+ auto
+ __base(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ -> decltype(__base(__it, std::__iterator_category(__it)))
+ { return __base(__it, std::__iterator_category(__it)); }
+#endif
+
+#if __cplusplus < 201103L
+ template<typename _Iterator, typename _Sequence>
+ struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> >
+ { typedef _Iterator _Type; };
+#endif
+
+ template<typename _Iterator, typename _Sequence>
+ inline _Iterator
+ __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ { return __it.base(); }
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc
index 47b6f2f1dd3..1ad26e3e07b 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -38,12 +38,14 @@ namespace __gnu_debug
{
if (this->_M_singular())
return false;
+
if (__n == 0)
return true;
+
if (__n < 0)
{
std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(_M_get_sequence()->_M_base().begin(), base());
+ __get_distance_from_begin(*this);
bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
@@ -51,7 +53,7 @@ namespace __gnu_debug
else
{
std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), _M_get_sequence()->_M_base().end());
+ __get_distance_to_end(*this);
bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
@@ -61,37 +63,31 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
bool
_Safe_iterator<_Iterator, _Sequence>::
- _M_valid_range(const _Safe_iterator& __rhs) const
+ _M_valid_range(const _Safe_iterator& __rhs,
+ std::pair<difference_type, _Distance_precision>& __dist,
+ bool __check_dereferenceable) const
{
if (!_M_can_compare(__rhs))
return false;
- /* Determine if we can order the iterators without the help of
- the container */
- std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), __rhs.base());
- switch (__dist.second) {
- case __dp_equality:
- if (__dist.first == 0)
- return true;
- break;
-
- case __dp_sign:
- case __dp_exact:
- return __dist.first >= 0;
- }
+ /* Determine iterators order */
+ __dist = __get_distance(*this, __rhs);
+ switch (__dist.second)
+ {
+ case __dp_equality:
+ if (__dist.first == 0)
+ return true;
+ break;
- /* We can only test for equality, but check if one of the
- iterators is at an extreme. */
- /* Optim for classic [begin, it) or [it, end) ranges, limit checks
- * when code is valid. Note, for the special case of forward_list,
- * before_begin replaces the role of begin. */
- if (_M_is_beginnest() || __rhs._M_is_end())
- return true;
- if (_M_is_end() || __rhs._M_is_beginnest())
- return false;
+ case __dp_sign:
+ case __dp_exact:
+ // If range is not empty first iterator must be dereferenceable.
+ if (__dist.first > 0)
+ return !__check_dereferenceable || _M_dereferenceable();
+ return __dist.first == 0;
+ }
- // Assume that this is a valid range; we can't check anything else
+ // Assume that this is a valid range; we can't check anything else.
return true;
}
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h
index dcbe4400cac..350a1d249ed 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.h
+++ b/libstdc++-v3/include/debug/safe_local_iterator.h
@@ -322,7 +322,9 @@ namespace __gnu_debug
// Is the iterator range [*this, __rhs) valid?
bool
- _M_valid_range(const _Safe_local_iterator& __rhs) const;
+ _M_valid_range(const _Safe_local_iterator& __rhs,
+ std::pair<difference_type,
+ _Distance_precision>& __dist_info) const;
// The sequence this iterator references.
typename
@@ -440,8 +442,66 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
__valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
- const _Safe_local_iterator<_Iterator, _Sequence>& __last)
- { return __first._M_valid_range(__last); }
+ const _Safe_local_iterator<_Iterator, _Sequence>& __last,
+ typename _Distance_traits<_Iterator>::__type& __dist_info)
+ { return __first._M_valid_range(__last, __dist_info); }
+
+ /** Safe local iterators need a special method to get distance between each
+ other. */
+ template<typename _Iterator, typename _Sequence>
+ inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
+ _Distance_precision>
+ __get_distance(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
+ const _Safe_local_iterator<_Iterator, _Sequence>& __last,
+ std::input_iterator_tag)
+ {
+ if (__first.base() == __last.base())
+ return { 0, __dp_exact };
+
+ if (__first._M_is_begin())
+ {
+ if (__last._M_is_end())
+ return
+ {
+ __first._M_get_sequence()->bucket_size(__first.bucket()),
+ __dp_exact
+ };
+
+ return { 1, __dp_sign };
+ }
+
+ if (__first._M_is_end())
+ {
+ if (__last._M_is_begin())
+ return
+ {
+ -__first._M_get_sequence()->bucket_size(__first.bucket()),
+ __dp_exact
+ };
+
+ return { -1, __dp_sign };
+ }
+
+ if (__last._M_is_begin())
+ return { -1, __dp_sign };
+
+ if (__last._M_is_end())
+ return { 1, __dp_sign };
+
+ return { 1, __dp_equality };
+ }
+
+#if __cplusplus < 201103L
+ template<typename _Iterator, typename _Sequence>
+ struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> >
+ { typedef _Iterator _Type; };
+#endif
+
+ template<typename _Iterator, typename _Sequence>
+ inline _Iterator
+ __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it)
+ { return __it.base(); }
+
} // namespace __gnu_debug
#include <debug/safe_local_iterator.tcc>
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc b/libstdc++-v3/include/debug/safe_local_iterator.tcc
index 455e4cd5dd7..f846bf78307 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc
@@ -34,17 +34,18 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
bool
_Safe_local_iterator<_Iterator, _Sequence>::
- _M_valid_range(const _Safe_local_iterator& __rhs) const
+ _M_valid_range(const _Safe_local_iterator& __rhs,
+ std::pair<difference_type, _Distance_precision>& __dist) const
{
if (!_M_can_compare(__rhs))
return false;
+
if (bucket() != __rhs.bucket())
return false;
/* Determine if we can order the iterators without the help of
the container */
- std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), __rhs.base());
+ __dist = __get_distance(*this, __rhs);
switch (__dist.second)
{
case __dp_equality:
@@ -57,15 +58,6 @@ namespace __gnu_debug
return __dist.first >= 0;
}
- /* We can only test for equality, but check if one of the
- iterators is at an extreme. */
- /* Optim for classic [begin, it) or [it, end) ranges, limit checks
- * when code is valid. */
- if (_M_is_begin() || __rhs._M_is_end())
- return true;
- if (_M_is_end() || __rhs._M_is_begin())
- return false;
-
// Assume that this is a valid range; we can't check anything else
return true;
}
diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h
index c13ee811aaa..1ca6dda9c0e 100644
--- a/libstdc++-v3/include/debug/set.h
+++ b/libstdc++-v3/include/debug/set.h
@@ -280,9 +280,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/stl_iterator.h b/libstdc++-v3/include/debug/stl_iterator.h
new file mode 100644
index 00000000000..d1e57ea75a0
--- /dev/null
+++ b/libstdc++-v3/include/debug/stl_iterator.h
@@ -0,0 +1,113 @@
+// Debugging support implementation -*- C++ -*-
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file debug/stl_iterator.h
+ * This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_STL_ITERATOR_H
+#define _GLIBCXX_DEBUG_STL_ITERATOR_H 1
+
+#include <debug/helper_functions.h>
+
+namespace __gnu_debug
+{
+ // Help Debug mode to see through reverse_iterator.
+ template<typename _Iterator>
+ inline bool
+ __valid_range(const std::reverse_iterator<_Iterator>& __first,
+ const std::reverse_iterator<_Iterator>& __last,
+ typename _Distance_traits<_Iterator>::__type& __dist)
+ { return __valid_range(__last.base(), __first.base(), __dist); }
+
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const std::reverse_iterator<_Iterator>& __first,
+ const std::reverse_iterator<_Iterator>& __last)
+ { return __get_distance(__last.base(), __first.base()); }
+
+#if __cplusplus < 201103L
+ template<typename _Iterator>
+ struct __is_safe_random_iterator<std::reverse_iterator<_Iterator> >
+ : __is_safe_random_iterator<_Iterator>
+ { };
+
+ template<typename _Iterator>
+ struct _Unsafe_type<std::reverse_iterator<_Iterator> >
+ {
+ typedef typename _Unsafe_type<_Iterator>::_Type _UnsafeType;
+ typedef std::reverse_iterator<_UnsafeType> _Type;
+ };
+
+ template<typename _Iterator>
+ inline std::reverse_iterator<typename _Unsafe_type<_Iterator>::_Type>
+ __unsafe(const std::reverse_iterator<_Iterator>& __it)
+ {
+ typedef typename _Unsafe_type<_Iterator>::_Type _UnsafeType;
+ return std::reverse_iterator<_UnsafeType>(__unsafe(__it.base()));
+ }
+#else
+ template<typename _Iterator>
+ inline auto
+ __base(const std::reverse_iterator<_Iterator>& __it)
+ -> decltype(std::__make_reverse_iterator(__base(__it.base())))
+ { return std::__make_reverse_iterator(__base(__it.base())); }
+
+ template<typename _Iterator>
+ inline auto
+ __unsafe(const std::reverse_iterator<_Iterator>& __it)
+ -> decltype(std::__make_reverse_iterator(__unsafe(__it.base())))
+ { return std::__make_reverse_iterator(__unsafe(__it.base())); }
+#endif
+
+#if __cplusplus >= 201103L
+ // Help Debug mode to see through move_iterator.
+ template<typename _Iterator>
+ inline bool
+ __valid_range(const std::move_iterator<_Iterator>& __first,
+ const std::move_iterator<_Iterator>& __last,
+ typename _Distance_traits<_Iterator>::__type& __dist)
+ { return __valid_range(__first.base(), __last.base(), __dist); }
+
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const std::move_iterator<_Iterator>& __first,
+ const std::move_iterator<_Iterator>& __last)
+ { return __get_distance(__first.base(), __last.base()); }
+
+ template<typename _Iterator>
+ inline auto
+ __unsafe(const std::move_iterator<_Iterator>& __it)
+ -> decltype(std::make_move_iterator(__unsafe(__it.base())))
+ { return std::make_move_iterator(__unsafe(__it.base())); }
+
+ template<typename _Iterator>
+ inline auto
+ __base(const std::move_iterator<_Iterator>& __it)
+ -> decltype(std::make_move_iterator(__base(__it.base())))
+ { return std::make_move_iterator(__base(__it.base())); }
+#endif
+}
+
+#endif
diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string
index f068ef04fe8..72ae88e5495 100644
--- a/libstdc++-v3/include/debug/string
+++ b/libstdc++-v3/include/debug/string
@@ -380,9 +380,15 @@ namespace __gnu_debug
basic_string&
append(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::append(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __dp_sign)
+ _Base::append(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::append(__first, __last);
+
this->_M_invalidate_all();
return *this;
}
@@ -452,9 +458,15 @@ namespace __gnu_debug
basic_string&
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
return *this;
}
@@ -533,9 +545,15 @@ namespace __gnu_debug
void
insert(iterator __p, _InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__p, __first, __last);
- _Base::insert(__p.base(), __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range2(__p, __first, __last, __dist);
+
+ if (__dist.second >= __dp_sign)
+ _Base::insert(__p.base(), __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__p.base(), __first, __last);
+
this->_M_invalidate_all();
}
@@ -676,8 +694,17 @@ namespace __gnu_debug
_InputIterator __j1, _InputIterator __j2)
{
__glibcxx_check_erase_range(__i1, __i2);
- __glibcxx_check_valid_range(__j1, __j2);
- _Base::replace(__i1.base(), __i2.base(), __j1, __j2);
+
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__j1, __j2, __dist);
+
+ if (__dist.second >= __dp_sign)
+ _Base::replace(__i1.base(), __i2.base(),
+ __gnu_debug::__unsafe(__j1),
+ __gnu_debug::__unsafe(__j2));
+ else
+ _Base::replace(__i1.base(), __i2.base(), __j1, __j2);
+
this->_M_invalidate_all();
return *this;
}
diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map
index 3f46641d678..41e20d7f203 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -364,10 +364,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
+
_M_check_rehashed(__bucket_count);
}
@@ -809,10 +815,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
+
_M_check_rehashed(__bucket_count);
}
diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set
index 10a9c270ed0..1e6846140ab 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -355,10 +355,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
+
_M_check_rehashed(__bucket_count);
}
@@ -799,10 +805,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
+
_M_check_rehashed(__bucket_count);
}
diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector
index be679920949..310009756c0 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -244,9 +244,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
this->_M_update_guaranteed_capacity();
}
@@ -574,16 +580,21 @@ namespace __debug
insert(const_iterator __position,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
/* Hard to guess if invalidation will occur, because __last
- __first can't be calculated in all cases, so we just
punt here by checking if it did occur. */
_Base_iterator __old_begin = _M_base().begin();
difference_type __offset = __position.base() - _Base::cbegin();
- _Base_iterator __res = _Base::insert(__position.base(),
- __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ _Base_iterator __res;
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ __res = _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ __res = _Base::insert(__position.base(), __first, __last);
if (_M_base().begin() != __old_begin)
this->_M_invalidate_all();
@@ -598,15 +609,19 @@ namespace __debug
insert(iterator __position,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
/* Hard to guess if invalidation will occur, because __last
- __first can't be calculated in all cases, so we just
punt here by checking if it did occur. */
_Base_iterator __old_begin = _M_base().begin();
difference_type __offset = __position.base() - _Base::begin();
- _Base::insert(__position.base(), __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__position.base(), __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__position.base(), __first, __last);
if (_M_base().begin() != __old_begin)
this->_M_invalidate_all();
diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional
index 0472f593df5..c6b9800f7a6 100644
--- a/libstdc++-v3/include/experimental/functional
+++ b/libstdc++-v3/include/experimental/functional
@@ -124,7 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _RAIter, typename _Unused>
__boyer_moore_array_base(_RAIter __pat, size_t __patlen,
_Unused&&, _Pred&& __pred)
- : _M_bad_char{ {}, std::move(__pred) }
+ : _M_bad_char{ std::array<_Tp, _Len>{}, std::move(__pred) }
{
std::get<0>(_M_bad_char).fill(__patlen);
if (__patlen > 0)
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 0504012cbd1..59b992a4a06 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -457,63 +457,236 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
};
+
+ // Concept utility functions, reused in conditionally-explicit
+ // constructors.
+ template<bool, typename... _Elements>
+ struct _TC
+ {
+ template<typename... _UElements>
+ static constexpr bool _ConstructibleTuple()
+ {
+ return __and_<is_constructible<_Elements, const _UElements&>...>::value;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _ImplicitlyConvertibleTuple()
+ {
+ return __and_<is_convertible<const _UElements&, _Elements>...>::value;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _MoveConstructibleTuple()
+ {
+ return __and_<is_constructible<_Elements, _UElements&&>...>::value;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _ImplicitlyMoveConvertibleTuple()
+ {
+ return __and_<is_convertible<_UElements&&, _Elements>...>::value;
+ }
+ };
+
+ template<typename... _Elements>
+ struct _TC<false, _Elements...>
+ {
+ template<typename... _UElements>
+ static constexpr bool _ConstructibleTuple()
+ {
+ return false;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _ImplicitlyConvertibleTuple()
+ {
+ return false;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _MoveConstructibleTuple()
+ {
+ return false;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _ImplicitlyMoveConvertibleTuple()
+ {
+ return false;
+ }
+ };
+
/// Primary class template, tuple
template<typename... _Elements>
class tuple : public _Tuple_impl<0, _Elements...>
{
typedef _Tuple_impl<0, _Elements...> _Inherited;
+ // Used for constraining the default constructor so
+ // that it becomes dependent on the constraints.
+ template<typename _Dummy>
+ struct _TC2
+ {
+ static constexpr bool _DefaultConstructibleTuple()
+ {
+ return __and_<is_default_constructible<_Elements>...>::value;
+ }
+ };
+
public:
+ template<typename _Dummy = void,
+ typename enable_if<_TC2<_Dummy>::
+ _DefaultConstructibleTuple(),
+ bool>::type = true>
constexpr tuple()
: _Inherited() { }
- explicit
- constexpr tuple(const _Elements&... __elements)
+ // Shortcut for the cases where constructors taking _Elements...
+ // need to be constrained.
+ template<typename _Dummy> using _TCC =
+ _TC<is_same<_Dummy, void>::value,
+ _Elements...>;
+
+ template<typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_Elements...>()
+ && _TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_Elements...>()
+ && (sizeof...(_Elements) >= 1),
+ bool>::type=true>
+ constexpr tuple(const _Elements&... __elements)
: _Inherited(__elements...) { }
- template<typename... _UElements, typename = typename
- enable_if<__and_<is_convertible<_UElements,
- _Elements>...>::value>::type>
- explicit
+ template<typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_Elements...>()
+ && !_TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_Elements...>()
+ && (sizeof...(_Elements) >= 1),
+ bool>::type=false>
+ explicit constexpr tuple(const _Elements&... __elements)
+ : _Inherited(__elements...) { }
+
+ // Shortcut for the cases where constructors taking _UElements...
+ // need to be constrained.
+ template<typename... _UElements> using _TMC =
+ _TC<(sizeof...(_Elements) == sizeof...(_UElements)),
+ _Elements...>;
+
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>()
+ && (sizeof...(_Elements) >= 1),
+ bool>::type=true>
constexpr tuple(_UElements&&... __elements)
+ : _Inherited(std::forward<_UElements>(__elements)...) { }
+
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>()
+ && (sizeof...(_Elements) >= 1),
+ bool>::type=false>
+ explicit constexpr tuple(_UElements&&... __elements)
: _Inherited(std::forward<_UElements>(__elements)...) { }
constexpr tuple(const tuple&) = default;
constexpr tuple(tuple&&) = default;
- template<typename... _UElements, typename = typename
- enable_if<__and_<is_convertible<const _UElements&,
- _Elements>...>::value>::type>
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _ConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyConvertibleTuple<_UElements...>(),
+ bool>::type=true>
constexpr tuple(const tuple<_UElements...>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
- template<typename... _UElements, typename = typename
- enable_if<__and_<is_convertible<_UElements,
- _Elements>...>::value>::type>
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _ConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit constexpr tuple(const tuple<_UElements...>& __in)
+ : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
+ { }
+
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=true>
constexpr tuple(tuple<_UElements...>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit constexpr tuple(tuple<_UElements...>&& __in)
+ : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
+
// Allocator-extended constructors.
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a)
: _Inherited(__tag, __a) { }
- template<typename _Alloc>
+ template<typename _Alloc, typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_Elements...>()
+ && _TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_Elements...>(),
+ bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const _Elements&... __elements)
: _Inherited(__tag, __a, __elements...) { }
- template<typename _Alloc, typename... _UElements, typename = typename
- enable_if<sizeof...(_UElements)
- == sizeof...(_Elements)>::type>
+ template<typename _Alloc, typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_Elements...>()
+ && !_TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_Elements...>(),
+ bool>::type=false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const _Elements&... __elements)
+ : _Inherited(__tag, __a, __elements...) { }
+
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
_UElements&&... __elements)
: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
{ }
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ _UElements&&... __elements)
+ : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
+ { }
+
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
@@ -522,24 +695,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
- template<typename _Alloc, typename... _UElements, typename = typename
- enable_if<sizeof...(_UElements)
- == sizeof...(_Elements)>::type>
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _ConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyConvertibleTuple<_UElements...>(),
+ bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const tuple<_UElements...>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
- template<typename _Alloc, typename... _UElements, typename = typename
- enable_if<sizeof...(_UElements)
- == sizeof...(_Elements)>::type>
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _ConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const tuple<_UElements...>& __in)
+ : _Inherited(__tag, __a,
+ static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
+ { }
+
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
tuple<_UElements...>&& __in)
: _Inherited(__tag, __a,
static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
{ }
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple<_UElements...>&& __in)
+ : _Inherited(__tag, __a,
+ static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
+ { }
+
tuple&
operator=(const tuple& __in)
{
@@ -582,7 +785,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
// Explicit specialization, zero-element tuple.
- template<>
+ template<>
class tuple<>
{
public:
@@ -597,65 +800,190 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Tuple_impl<0, _T1, _T2> _Inherited;
public:
+ template <typename _U1 = _T1,
+ typename _U2 = _T2,
+ typename enable_if<__and_<
+ is_default_constructible<_U1>,
+ is_default_constructible<_U2>>
+ ::value, bool>::type = true>
+
constexpr tuple()
: _Inherited() { }
- explicit
- constexpr tuple(const _T1& __a1, const _T2& __a2)
- : _Inherited(__a1, __a2) { }
-
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
- explicit
+ // Shortcut for the cases where constructors taking _T1, _T2
+ // need to be constrained.
+ template<typename _Dummy> using _TCC =
+ _TC<is_same<_Dummy, void>::value, _T1, _T2>;
+
+ template<typename _Dummy = void, typename
+ enable_if<_TCC<_Dummy>::template
+ _ConstructibleTuple<_T1, _T2>()
+ && _TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_T1, _T2>(),
+ bool>::type = true>
+ constexpr tuple(const _T1& __a1, const _T2& __a2)
+ : _Inherited(__a1, __a2) { }
+
+ template<typename _Dummy = void, typename
+ enable_if<_TCC<_Dummy>::template
+ _ConstructibleTuple<_T1, _T2>()
+ && !_TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_T1, _T2>(),
+ bool>::type = false>
+ explicit constexpr tuple(const _T1& __a1, const _T2& __a2)
+ : _Inherited(__a1, __a2) { }
+
+ // Shortcut for the cases where constructors taking _U1, _U2
+ // need to be constrained.
+ using _TMC = _TC<true, _T1, _T2>;
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(_U1&& __a1, _U2&& __a2)
: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
+ : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
+
constexpr tuple(const tuple&) = default;
constexpr tuple(tuple&&) = default;
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<const _U1&, _T1>,
- is_convertible<const _U2&, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(const tuple<_U1, _U2>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(const tuple<_U1, _U2>& __in)
+ : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(tuple<_U1, _U2>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<const _U1&, _T1>,
- is_convertible<const _U2&, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(tuple<_U1, _U2>&& __in)
+ : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(const pair<_U1, _U2>& __in)
: _Inherited(__in.first, __in.second) { }
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(const pair<_U1, _U2>& __in)
+ : _Inherited(__in.first, __in.second) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(pair<_U1, _U2>&& __in)
: _Inherited(std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(pair<_U1, _U2>&& __in)
+ : _Inherited(std::forward<_U1>(__in.first),
+ std::forward<_U2>(__in.second)) { }
+
// Allocator-extended constructors.
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a)
: _Inherited(__tag, __a) { }
- template<typename _Alloc>
+ template<typename _Alloc, typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_T1, _T2>()
+ && _TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_T1, _T2>(),
+ bool>::type=true>
+
tuple(allocator_arg_t __tag, const _Alloc& __a,
const _T1& __a1, const _T2& __a2)
: _Inherited(__tag, __a, __a1, __a2) { }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_T1, _T2>()
+ && !_TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_T1, _T2>(),
+ bool>::type=false>
+
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const _T1& __a1, const _T2& __a2)
+ : _Inherited(__tag, __a, __a1, __a2) { }
+
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
: _Inherited(__tag, __a, std::forward<_U1>(__a1),
std::forward<_U2>(__a2)) { }
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ _U1&& __a1, _U2&& __a2)
+ : _Inherited(__tag, __a, std::forward<_U1>(__a1),
+ std::forward<_U2>(__a2)) { }
+
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
@@ -664,28 +992,92 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const tuple<_U1, _U2>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
{ }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const tuple<_U1, _U2>& __in)
+ : _Inherited(__tag, __a,
+ static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
+ { }
+
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
{ }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple<_U1, _U2>&& __in)
+ : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
+ { }
+
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const pair<_U1, _U2>& __in)
: _Inherited(__tag, __a, __in.first, __in.second) { }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const pair<_U1, _U2>& __in)
+ : _Inherited(__tag, __a, __in.first, __in.second) { }
+
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ pair<_U1, _U2>&& __in)
+ : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
+ std::forward<_U2>(__in.second)) { }
+
tuple&
operator=(const tuple& __in)
{
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
new file mode 100644
index 00000000000..50edda9151a
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
@@ -0,0 +1,108 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <utility>
+
+struct Explicit
+{
+ Explicit() = default;
+ explicit Explicit(int) {}
+};
+
+std::pair<int, int> f1() {return {1,2};}
+
+std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
+
+std::pair<long, long> f3() {return std::pair<int, int>{1,2};}
+
+std::pair<Explicit, Explicit> f4()
+{
+ return std::pair<int, int>{1,2}; // { dg-error "could not convert" }
+}
+
+std::pair<long, long> f5() {return {1,2};}
+
+std::pair<int, int> v0{1,2};
+
+std::pair<Explicit, Explicit> v1{1,2};
+
+std::pair<Explicit, Explicit> v2 = {1,2}; // { dg-error "explicit" }
+
+std::pair<Explicit, Explicit> v3{std::pair<int,int>{1,2}};
+
+std::pair<Explicit, Explicit> v4 =
+ std::pair<int,int>{1,2}; // { dg-error "conversion" }
+
+std::pair<char *, char *> v5(0,0);
+
+std::pair<long, long> v6{1,2};
+
+std::pair<long, long> v7 = {1,2};
+
+std::pair<long, long> v8{std::pair<int,int>{1,2}};
+
+std::pair<long, long> v9 = std::pair<int,int>{1,2};
+
+std::pair<Explicit, Explicit> v10{v0};
+
+std::pair<Explicit, Explicit> v11 = v0; // { dg-error "conversion" }
+
+std::pair<long, long> v12{v0};
+
+std::pair<long, long> v13 = v0;
+
+void f6(std::pair<Explicit, Explicit>) {}
+
+void f7(std::pair<long, long>) {}
+
+void test_arg_passing()
+{
+ f6(v0); // { dg-error "could not convert" }
+ f6(v1);
+ f6({1,2}); // { dg-error "explicit" }
+ f6(std::pair<Explicit, Explicit>{});
+ f6(std::pair<int, int>{}); // { dg-error "could not convert" }
+ f7(v0);
+ f7(v6);
+ f7({1,2});
+ f7(std::pair<int, int>{});
+ f7(std::pair<long, long>{});
+}
+
+struct MoveOnly
+{
+ MoveOnly() = default;
+ MoveOnly(MoveOnly&&) {}
+};
+
+struct ExplicitMoveOnly
+{
+ ExplicitMoveOnly() = default;
+ ExplicitMoveOnly(ExplicitMoveOnly&&) {}
+ explicit ExplicitMoveOnly(MoveOnly&&) {}
+};
+
+std::pair<int*, ExplicitMoveOnly> v14{0, MoveOnly{}};
+std::pair<ExplicitMoveOnly, int*> v15{MoveOnly{}, 0};
+
+std::pair<int*, ExplicitMoveOnly> v16 =
+ {0, MoveOnly{}}; // { dg-error "explicit" }
+std::pair<ExplicitMoveOnly, int*> v17 =
+ {MoveOnly{}, 0}; // { dg-error "explicit" }
diff --git a/libstdc++-v3/testsuite/20_util/pair/piecewise.cc b/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
index bcdab7d60c7..40ab16b14b9 100644
--- a/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
@@ -69,20 +69,20 @@ void test01()
{
bool test __attribute__((unused)) = true;
- std::pair<type_one, type_zero> pp0(std::piecewise_construct_t(),
+ std::pair<type_one, type_zero> pp0(std::piecewise_construct,
std::forward_as_tuple(-3),
std::forward_as_tuple());
VERIFY( pp0.first.get() == -3 );
VERIFY( pp0.second.get() == 757 );
- std::pair<type_one, type_two> pp1(std::piecewise_construct_t(),
+ std::pair<type_one, type_two> pp1(std::piecewise_construct,
std::forward_as_tuple(6),
std::forward_as_tuple(5, 4));
VERIFY( pp1.first.get() == 6 );
VERIFY( pp1.second.get1() == 5 );
VERIFY( pp1.second.get2() == 4 );
- std::pair<type_two, type_two> pp2(std::piecewise_construct_t(),
+ std::pair<type_two, type_two> pp2(std::piecewise_construct,
std::forward_as_tuple(2, 1),
std::forward_as_tuple(-1, -3));
VERIFY( pp2.first.get1() == 2 );
diff --git a/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc b/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc
new file mode 100644
index 00000000000..603b7c57074
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc
@@ -0,0 +1,41 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <utility>
+#include <type_traits>
+
+// DR 2367, pair and tuple are not correctly implemented for is_constructible with no args
+void test_default_constructible()
+{
+ struct X
+ {
+ X() = delete;
+ };
+
+ typedef std::pair<int, X> P;
+ static_assert(!std::is_constructible<P>::value, "");
+ static_assert(!std::is_default_constructible<P>::value, "");
+}
+
+int main()
+{
+ test_default_constructible();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
new file mode 100644
index 00000000000..114a4906f1f
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
@@ -0,0 +1,282 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tuple>
+#include <utility>
+#include <memory>
+
+struct Explicit
+{
+ Explicit() = default;
+ explicit Explicit(int) {}
+};
+
+std::tuple<int> f1a() {return {1};}
+std::tuple<int, int> f1b() {return {1,2};}
+std::tuple<int, int, int> f1c() {return {1,2,3};}
+
+std::tuple<Explicit> f2_a() {return {1};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> f2_b() {return {1,2};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> f2_c() {return {1,2,3};} // { dg-error "explicit" }
+
+std::tuple<long> f3_a() {return std::tuple<int>{1};}
+std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};}
+std::tuple<long, long, long> f3_c() {return std::tuple<int, int, int>{1,2,3};}
+
+std::tuple<Explicit> f4_a()
+{
+ return std::tuple<int>{1}; // { dg-error "could not convert" }
+}
+std::tuple<Explicit, Explicit> f4_b()
+{
+ return std::tuple<int, int>{1,2}; // { dg-error "could not convert" }
+}
+std::tuple<Explicit, Explicit, Explicit> f4_c()
+{
+ return std::tuple<int, int,int>{1,2,3}; // { dg-error "could not convert" }
+}
+
+std::tuple<long> f5_a() {return {1};}
+std::tuple<long, long> f5_b() {return {1,2};}
+std::tuple<long, long, long> f5_c() {return {1,2,3};}
+
+std::tuple<int, int> fp1() {return std::pair<int, int>{1,2}; }
+std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; }
+std::tuple<Explicit, Explicit> fp3()
+ {return std::pair<int, int>{1,2}; } // { dg-error "could not convert" }
+
+std::tuple<int> v0_a{1};
+std::tuple<int, int> v0_b{1,2};
+std::tuple<int, int, int> v0_c{1,2,3};
+
+std::tuple<Explicit> v1_a{1};
+std::tuple<Explicit, Explicit> v1_b{1,2};
+std::tuple<Explicit, Explicit, Explicit> v1_c{1,2,3};
+
+std::tuple<Explicit> v2_a = {1}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> v2_b = {1,2}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> v2_c = {1,2,3}; // { dg-error "explicit" }
+
+std::tuple<Explicit> v3_a{std::tuple<int>{1}};
+std::tuple<Explicit, Explicit> v3_b{std::tuple<int,int>{1,2}};
+std::tuple<Explicit, Explicit, Explicit> v3_c{std::tuple<int,int,int>{1,2,3}};
+
+std::tuple<Explicit, Explicit> v4_a =
+ std::tuple<int>{1}; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit> v4_b =
+ std::tuple<int,int>{1,2}; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit, Explicit> v4_c =
+ std::tuple<int,int,int>{1,2,3}; // { dg-error "conversion" }
+
+std::tuple<long> v6_a{1};
+std::tuple<long, long> v6_b{1,2};
+std::tuple<long, long, long> v6_c{1,2,3};
+
+std::tuple<long> v7_a = {1};
+std::tuple<long, long> v7_b = {1,2};
+std::tuple<long, long, long> v7_c = {1,2,3};
+
+std::tuple<long> v8_a{std::tuple<int>{1}};
+std::tuple<long, long> v8_b{std::tuple<int,int>{1,2}};
+std::tuple<long, long, long> v8_c{std::tuple<int,int,int>{1,2,3}};
+
+std::tuple<long> v9_a = std::tuple<int>{1};
+std::tuple<long, long> v9_b = std::tuple<int,int>{1,2};
+std::tuple<long, long, long> v9_c = std::tuple<int,int,int>{1,2,3};
+
+std::tuple<Explicit> v10_a{v0_a};
+std::tuple<Explicit, Explicit> v10_b{v0_b};
+std::tuple<Explicit, Explicit, Explicit> v10_c{v0_c};
+
+std::tuple<Explicit> v11_a = v0_a; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit> v11_b = v0_b; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit, Explicit> v11_c
+ = v0_c; // { dg-error "conversion" }
+
+std::tuple<long> v12_a{v0_a};
+std::tuple<long, long> v12_b{v0_b};
+std::tuple<long, long, long> v12_c{v0_c};
+
+std::tuple<long> v13_a = v0_a;
+std::tuple<long, long> v13_b = v0_b;
+std::tuple<long, long, long> v13_c = v0_c;
+
+std::tuple<int, int> v14{std::pair<int, int>{1,2}};
+std::tuple<long, long> v15{std::pair<int, int>{1,2}};
+std::tuple<Explicit, Explicit> v16{std::pair<int, int>{1,2}};
+
+std::tuple<int, int> v17 = std::pair<int, int>{1,2};
+std::tuple<long, long> v18 = std::pair<int, int>{1,2};
+std::tuple<Explicit, Explicit> v19
+ = std::pair<int, int>{1,2}; // { dg-error "conversion" }
+
+std::pair<int, int> v20;
+
+std::tuple<int, int> v21{v20};
+std::tuple<long, long> v22{v20};
+std::tuple<Explicit, Explicit> v23{v20};
+
+std::tuple<int, int> v24 = v20;
+std::tuple<long, long> v25 = v20;
+std::tuple<Explicit, Explicit> v26 = v20; // { dg-error "conversion" }
+
+std::tuple<int> v27_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<int, int> v27_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<int, int, int> v27_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<long> v28_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<long, long> v28_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<long, long, long>
+ v28_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<Explicit> v29_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<Explicit, Explicit>
+ v29_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<Explicit, Explicit, Explicit>
+ v29_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<int> v30_a = {std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<int, int> v30_b = {std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<int, int, int> v30_c
+ = {std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<long> v31_a = {std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<long, long> v31_b = {std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<long, long, long>
+ v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<Explicit> v32_a
+ = {std::allocator_arg, std::allocator<int>{}, 1}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> v32_b
+ = {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> v32_c
+ = {std::allocator_arg, std::allocator<int>{}, 1,2,3}; // { dg-error "explicit" }
+
+std::tuple<int, int> v33{std::allocator_arg, std::allocator<int>{},
+ std::pair<int, int>{1, 2}};
+
+std::tuple<long, long> v34{std::allocator_arg, std::allocator<int>{},
+ std::pair<int, int>{1, 2}};
+
+std::tuple<Explicit, Explicit>
+ v35{std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}};
+
+std::tuple<int, int> v36 = {std::allocator_arg, std::allocator<int>{},
+ std::pair<int, int>{1, 2}};
+
+std::tuple<long, long> v37 = {std::allocator_arg, std::allocator<int>{},
+ std::pair<int, int>{1, 2}};
+
+std::tuple<Explicit, Explicit> v38
+= {std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}}; // { dg-error "explicit" }
+
+std::tuple<int, int> v39{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<long, long> v40{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<Explicit, Explicit>
+ v41{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<int, int> v42 = {std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<long, long> v43 = {std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<Explicit, Explicit> v44
+= {std::allocator_arg, std::allocator<int>{}, v20}; // { dg-error "explicit" }
+
+struct DeletedCopy
+{
+ DeletedCopy(int);
+ DeletedCopy(const DeletedCopy&) = delete;
+};
+
+std::tuple<DeletedCopy> v45{42};
+std::tuple<DeletedCopy> v46{std::allocator_arg,
+ std::allocator<DeletedCopy>{}, 42};
+
+struct Sanity
+{
+ int v;
+};
+
+std::tuple<int, Sanity> v47(3, {42});
+std::tuple<int, int, Sanity> v48(3, 4, {42});
+std::tuple<int, Sanity> v49(std::allocator_arg,
+ std::allocator<Sanity>{},
+ 3, {42});
+std::tuple<int, int, Sanity> v50(std::allocator_arg,
+ std::allocator<Sanity>{},
+ 3, 4, {42});
+
+void f6_a(std::tuple<Explicit>) {}
+void f6_b(std::tuple<Explicit, Explicit>) {}
+void f6_c(std::tuple<Explicit, Explicit, Explicit>) {}
+
+void f7_a(std::tuple<long>) {}
+void f7_b(std::tuple<long, long>) {}
+void f7_c(std::tuple<long, long, long>) {}
+
+void test_arg_passing()
+{
+ f6_a(v0_a); // { dg-error "could not convert" }
+ f6_b(v0_b); // { dg-error "could not convert" }
+ f6_c(v0_c); // { dg-error "could not convert" }
+ f6_b(v20); // { dg-error "could not convert" }
+
+ f6_a(v1_a);
+ f6_b(v1_b);
+ f6_c(v1_c);
+
+ f6_a({1}); // { dg-error "explicit" }
+ f6_b({1,2}); // { dg-error "explicit" }
+ f6_c({1,2,3}); // { dg-error "explicit" }
+
+ f6_a(std::tuple<Explicit>{});
+ f6_b(std::tuple<Explicit, Explicit>{});
+ f6_c(std::tuple<Explicit, Explicit, Explicit>{});
+
+ f6_a(std::tuple<int>{}); // { dg-error "could not convert" }
+ f6_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
+ f6_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
+ f6_b(std::pair<int, int>{}); // { dg-error "could not convert" }
+
+ f7_a(v0_a);
+ f7_b(v0_b);
+ f7_c(v0_c);
+ f7_b(v20);
+
+ f7_a(v6_a);
+ f7_b(v6_b);
+ f7_c(v6_c);
+
+ f7_a({1});
+ f7_b({1,2});
+ f7_c({1,2,3});
+
+ f7_a(std::tuple<int>{});
+ f7_b(std::tuple<int, int>{});
+ f7_c(std::tuple<int, int, int>{});
+ f7_b(std::pair<int, int>{});
+
+
+ f7_a(std::tuple<long>{});
+ f7_b(std::tuple<long, long>{});
+ f7_c(std::tuple<long, long, long>{});
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc b/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc
new file mode 100644
index 00000000000..d3b975bd0f1
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc
@@ -0,0 +1,47 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tuple>
+#include <type_traits>
+
+// DR 2367, pair and tuple are not correctly implemented for is_constructible with no args
+void test_default_constructible()
+{
+ struct X
+ {
+ X() = delete;
+ };
+
+ typedef std::tuple<int, X> T;
+ static_assert(!std::is_constructible<T>::value, "");
+ static_assert(!std::is_default_constructible<T>::value, "");
+
+ typedef std::tuple<int, int, X> T2;
+ static_assert(!std::is_constructible<T2>::value, "");
+ static_assert(!std::is_default_constructible<T2>::value, "");
+
+
+}
+
+int main()
+{
+ test_default_constructible();
+ return 0;
+}