summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-10-31 16:43:41 -0400
committerJason Merrill <jason@redhat.com>2010-10-31 16:43:41 -0400
commit259d9cd27680549da5fdd21e6da1113292bdf68e (patch)
tree68a25e04066b49710ffe510f15087ce8940acbf7
parentab06fd052b678216c0cf12e307ae688f3f34a5d2 (diff)
parentf54453042eb4db352d729210fed67db58cb61b7e (diff)
downloadgcc-259d9cd27680549da5fdd21e6da1113292bdf68e.tar.gz
Merge remote branch 'trunk' into constexpr
Conflicts: gcc/cp/decl.c
-rw-r--r--boehm-gc/ChangeLog15
-rw-r--r--boehm-gc/Makefile.am25
-rw-r--r--boehm-gc/Makefile.in30
-rwxr-xr-xboehm-gc/configure53
-rw-r--r--boehm-gc/configure.ac48
-rw-r--r--boehm-gc/include/Makefile.in2
-rw-r--r--gcc/ChangeLog488
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog8
-rw-r--r--gcc/ada/gcc-interface/trans.c72
-rw-r--r--gcc/ada/gcc-interface/utils2.c8
-rw-r--r--gcc/builtins.c4
-rw-r--r--gcc/c-family/ChangeLog33
-rw-r--r--gcc/c-family/c-ada-spec.c31
-rw-r--r--gcc/c-family/c-common.c3
-rw-r--r--gcc/c-family/c-common.h11
-rw-r--r--gcc/c-family/stub-objc.c14
-rw-r--r--gcc/c-parser.c22
-rw-r--r--gcc/c-typeck.c59
-rw-r--r--gcc/combine.c222
-rw-r--r--gcc/config/arc/arc.c69
-rw-r--r--gcc/config/arc/arc.h55
-rw-r--r--gcc/config/arm/arm.c8
-rw-r--r--gcc/config/cris/cris.c57
-rw-r--r--gcc/config/cris/cris.h18
-rw-r--r--gcc/config/crx/crx-protos.h2
-rw-r--r--gcc/config/crx/crx.c30
-rw-r--r--gcc/config/crx/crx.h6
-rw-r--r--gcc/config/fr30/fr30-protos.h3
-rw-r--r--gcc/config/fr30/fr30.c40
-rw-r--r--gcc/config/fr30/fr30.h17
-rw-r--r--gcc/config/frv/frv-protos.h7
-rw-r--r--gcc/config/frv/frv.c42
-rw-r--r--gcc/config/frv/frv.h28
-rw-r--r--gcc/config/h8300/h8300-protos.h2
-rw-r--r--gcc/config/h8300/h8300.c31
-rw-r--r--gcc/config/h8300/h8300.h29
-rw-r--r--gcc/config/i386/i386.c95
-rw-r--r--gcc/config/i386/sse.md72
-rw-r--r--gcc/config/ia64/ia64-protos.h4
-rw-r--r--gcc/config/ia64/ia64.c60
-rw-r--r--gcc/config/ia64/ia64.h21
-rw-r--r--gcc/config/iq2000/iq2000-protos.h2
-rw-r--r--gcc/config/iq2000/iq2000.c37
-rw-r--r--gcc/config/iq2000/iq2000.h6
-rw-r--r--gcc/config/lm32/lm32-protos.h2
-rw-r--r--gcc/config/lm32/lm32.c27
-rw-r--r--gcc/config/lm32/lm32.h6
-rw-r--r--gcc/config/m68hc11/m68hc11-protos.h10
-rw-r--r--gcc/config/m68hc11/m68hc11.c21
-rw-r--r--gcc/config/m68hc11/m68hc11.h21
-rw-r--r--gcc/config/mcore/mcore-protos.h3
-rw-r--r--gcc/config/mcore/mcore.c26
-rw-r--r--gcc/config/mcore/mcore.h12
-rw-r--r--gcc/config/mn10300/mn10300-protos.h4
-rw-r--r--gcc/config/mn10300/mn10300.c175
-rw-r--r--gcc/config/mn10300/mn10300.h45
-rw-r--r--gcc/config/mn10300/mn10300.md1369
-rw-r--r--gcc/config/mn10300/mn10300.opt10
-rw-r--r--gcc/config/mn10300/t-mn103004
-rw-r--r--gcc/config/moxie/moxie-protos.h4
-rw-r--r--gcc/config/moxie/moxie.c28
-rw-r--r--gcc/config/moxie/moxie.h13
-rw-r--r--gcc/config/pdp11/pdp11-protos.h6
-rw-r--r--gcc/config/pdp11/pdp11.c222
-rw-r--r--gcc/config/pdp11/pdp11.h35
-rw-r--r--gcc/config/pdp11/pdp11.md229
-rw-r--r--gcc/config/pdp11/predicates.md18
-rw-r--r--gcc/config/picochip/picochip.c3
-rw-r--r--gcc/config/score/score.h21
-rw-r--r--gcc/config/sh/sh.c5
-rw-r--r--gcc/config/sparc/sol2-unwind.h59
-rw-r--r--gcc/config/stormy16/stormy16-protos.h7
-rw-r--r--gcc/config/stormy16/stormy16.c36
-rw-r--r--gcc/config/stormy16/stormy16.h6
-rw-r--r--gcc/cp/ChangeLog26
-rw-r--r--gcc/cp/class.c11
-rw-r--r--gcc/cp/parser.c20
-rw-r--r--gcc/cp/typeck.c6
-rw-r--r--gcc/doc/extend.texi18
-rw-r--r--gcc/doc/invoke.texi19
-rw-r--r--gcc/doc/tm.texi36
-rw-r--r--gcc/doc/tm.texi.in32
-rw-r--r--gcc/emit-rtl.c81
-rw-r--r--gcc/fold-const.c12
-rw-r--r--gcc/fortran/ChangeLog38
-rw-r--r--gcc/fortran/frontend-passes.c6
-rw-r--r--gcc/fortran/gfortran.h3
-rw-r--r--gcc/fortran/interface.c34
-rw-r--r--gcc/fortran/invoke.texi22
-rw-r--r--gcc/fortran/lang.opt10
-rw-r--r--gcc/fortran/options.c12
-rw-r--r--gcc/fortran/parse.c4
-rw-r--r--gcc/lower-subreg.c12
-rw-r--r--gcc/objc/ChangeLog91
-rw-r--r--gcc/objc/objc-act.c1346
-rw-r--r--gcc/objc/objc-act.h58
-rw-r--r--gcc/objc/objc-tree.def18
-rw-r--r--gcc/recog.c9
-rw-r--r--gcc/stmt.c4
-rw-r--r--gcc/target.def20
-rw-r--r--gcc/targhooks.c10
-rw-r--r--gcc/targhooks.h2
-rw-r--r--gcc/testsuite/ChangeLog146
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20101011-1.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vector-shift.c48
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vector-shift1.c17
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vector-shift2.c59
-rw-r--r--gcc/testsuite/gcc.dg/simd-1b.c4
-rw-r--r--gcc/testsuite/gcc.dg/stack-usage-1.c7
-rw-r--r--gcc/testsuite/gcc.dg/tls/thr-init-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tls/thr-init-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/tls/thr-init-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/tls/thr-init-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/vector-shift2.c60
-rw-r--r--gcc/testsuite/gcc.dg/vector-shift.c14
-rw-r--r--gcc/testsuite/gcc.dg/vector-shift1.c18
-rw-r--r--gcc/testsuite/gcc.dg/vector-shift3.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/fma3-builtin-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-builtin-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr46153.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr46226.c35
-rw-r--r--gcc/testsuite/gfortran.dg/class_dummy_3.f0330
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_generic_10.f0332
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-10.mm100
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-11.mm43
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-2.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-4.mm31
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-5.mm38
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-6.mm60
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-7.mm57
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-8.mm57
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-9.mm49
-rw-r--r--gcc/testsuite/obj-c++.dg/property/dynamic-1.mm8
-rw-r--r--gcc/testsuite/obj-c++.dg/property/dynamic-2.mm46
-rw-r--r--gcc/testsuite/obj-c++.dg/property/fsf-property-basic.mm45
-rw-r--r--gcc/testsuite/obj-c++.dg/property/fsf-property-method-access.mm30
-rw-r--r--gcc/testsuite/obj-c++.dg/property/fsf-property-named-ivar.mm27
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-1.mm5
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-1.mm9
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-2.mm3
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-3.mm12
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-4.mm9
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-5.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-7.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/property/synthesize-1.mm28
-rw-r--r--gcc/testsuite/obj-c++.dg/property/synthesize-2.mm51
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-10.m100
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-11.m43
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-2.m4
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-4.m31
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-5.m34
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-6.m60
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-7.m57
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-8.m57
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-9.m49
-rw-r--r--gcc/testsuite/objc.dg/property/dynamic-1.m8
-rw-r--r--gcc/testsuite/objc.dg/property/dynamic-2.m44
-rw-r--r--gcc/testsuite/objc.dg/property/fsf-property-basic.m33
-rw-r--r--gcc/testsuite/objc.dg/property/fsf-property-method-access.m28
-rw-r--r--gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m25
-rw-r--r--gcc/testsuite/objc.dg/property/property-1.m5
-rw-r--r--gcc/testsuite/objc.dg/property/property-2.m2
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-1.m9
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-2.m3
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-3.m8
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-4.m8
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-5.m4
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-7.m7
-rw-r--r--gcc/testsuite/objc.dg/property/synthesize-1.m28
-rw-r--r--gcc/testsuite/objc.dg/property/synthesize-2.m50
-rw-r--r--gcc/testsuite/objc.dg/torture/tls/thr-init-2.m2
-rw-r--r--gcc/testsuite/objc.dg/torture/tls/thr-init-3.m2
-rw-r--r--gcc/testsuite/objc.dg/torture/tls/thr-init.m2
-rw-r--r--gcc/tree-ssa-loop-im.c14
-rw-r--r--gcc/tree-vect-loop.c21
-rw-r--r--gcc/tree-vect-slp.c7
-rw-r--r--gcc/tree-vect-stmts.c19
-rw-r--r--gcc/tree.c35
-rw-r--r--gcc/tree.h1
-rw-r--r--libffi/ChangeLog38
-rw-r--r--libffi/src/arm/ffi.c231
-rw-r--r--libffi/src/arm/ffitarget.h18
-rw-r--r--libffi/src/arm/sysv.S173
-rw-r--r--libffi/testsuite/lib/libffi-dg.exp50
-rw-r--r--libffi/testsuite/libffi.call/cls_double_va.c2
-rw-r--r--libffi/testsuite/libffi.call/cls_longdouble_va.c2
-rw-r--r--libiberty/ChangeLog6
-rw-r--r--libiberty/functions.texi2
-rw-r--r--libiberty/setproctitle.c2
-rw-r--r--libstdc++-v3/ChangeLog50
-rw-r--r--libstdc++-v3/include/bits/hashtable.h295
-rw-r--r--libstdc++-v3/include/bits/hashtable_policy.h25
-rw-r--r--libstdc++-v3/include/bits/stl_function.h12
-rw-r--r--libstdc++-v3/include/debug/unordered_map36
-rw-r--r--libstdc++-v3/include/debug/unordered_set24
-rw-r--r--libstdc++-v3/include/profile/unordered_map51
-rw-r--r--libstdc++-v3/include/profile/unordered_set40
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc21
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc59
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc76
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc79
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc80
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc80
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc71
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc69
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_rvalref.h56
207 files changed, 7104 insertions, 2863 deletions
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index fd34e480320..cb05810ac59 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,18 @@
+2010-10-29 Paolo Bonzini <bonzini@gnu.org>
+
+ * configure: Regenerate.
+
+2010-10-28 Paolo Bonzini <bonzini@gnu.org>
+
+ * configure.ac: Rewrite DGUX check to use GC_CFLAGS, and -O0 check
+ to remove the need for MY_CFLAGS.
+ * Makefile.am: Do not use @...@ substitutions. Use AM_CXXFLAGS,
+ AM_CFLAGS and AM_LDFLAGS instead of redefining LTCOMPILE and LINK.
+ Use "override" to disable -O2 when required.
+ * configure: Regenerate.
+ * Makefile.in: Regenerate.
+ * include/Makefile.in: Regenerate.
+
2010-10-11 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* dyn_load.c: Fix typo.
diff --git a/boehm-gc/Makefile.am b/boehm-gc/Makefile.am
index df8de1e9e52..358614f3c68 100644
--- a/boehm-gc/Makefile.am
+++ b/boehm-gc/Makefile.am
@@ -33,20 +33,20 @@ mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_darwin_mach_dep.s \
rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
-extra_ldflags_libgc = @extra_ldflags_libgc@
-
# Include THREADLIBS here to ensure that the correct versions of
# linuxthread semaphore functions get linked:
-libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS) $(UNWINDLIBS)
-libgcjgc_la_DEPENDENCIES = @addobjs@
+libgcjgc_la_LIBADD = $(addobjs) $(THREADLIBS) $(UNWINDLIBS)
+libgcjgc_la_DEPENDENCIES = $(addobjs)
libgcjgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info 1:2:0 -rpath $(toolexeclibdir)
libgcjgc_la_LINK = $(LINK) $(libgcjgc_la_LDFLAGS)
-libgcjgc_convenience_la_LIBADD = @addobjs@
-libgcjgc_convenience_la_DEPENDENCIES = @addobjs@
+libgcjgc_convenience_la_LIBADD = $(addobjs)
+libgcjgc_convenience_la_DEPENDENCIES = $(addobjs)
-AM_CXXFLAGS = @GC_CFLAGS@
-AM_CFLAGS = @GC_CFLAGS@
+AM_CXXFLAGS = $(GC_CFLAGS)
+AM_CFLAGS = $(GC_CFLAGS)
+AM_LDFLAGS = $(shell $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
+override CFLAGS := $(filter-out $(O0_CFLAGS), $(CFLAGS)) $(O0_CFLAGS)
test_ldadd = libgcjgc.la $(THREADLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
@@ -93,15 +93,6 @@ libstaticrootslib_la_DEPENDENCIES = libgcjgc_convenience.la
.S.lo:
$(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $<
-## We have our own definition of LTCOMPILE because we want to use our
-## CFLAGS, not those passed in from the top level make.
-LTCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile \
- $(CC) $(DEFS) $(AM_CPPFLAGS) $(CPPFLAGS) \
- $(AM_CFLAGS) $(MY_CFLAGS) $(GC_CFLAGS)
-LTLDFLAGS = $(shell $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
-LINK = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
- $(CC) $(AM_CFLAGS) $(MY_CFLAGS) $(LTLDFLAGS) -o $@
-
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
# friends when we are called from the top level Makefile.
diff --git a/boehm-gc/Makefile.in b/boehm-gc/Makefile.in
index 051f6ce0cde..0d6bf5ca20d 100644
--- a/boehm-gc/Makefile.in
+++ b/boehm-gc/Makefile.in
@@ -108,7 +108,13 @@ depcomp =
am__depfiles_maybe =
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS)
LTCCASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS)
@@ -188,9 +194,9 @@ LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
-MY_CFLAGS = @MY_CFLAGS@
NM = @NM@
NMEDIT = @NMEDIT@
+O0_CFLAGS = @O0_CFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
@@ -301,14 +307,15 @@ sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
# Include THREADLIBS here to ensure that the correct versions of
# linuxthread semaphore functions get linked:
-libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS) $(UNWINDLIBS)
-libgcjgc_la_DEPENDENCIES = @addobjs@
+libgcjgc_la_LIBADD = $(addobjs) $(THREADLIBS) $(UNWINDLIBS)
+libgcjgc_la_DEPENDENCIES = $(addobjs)
libgcjgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info 1:2:0 -rpath $(toolexeclibdir)
libgcjgc_la_LINK = $(LINK) $(libgcjgc_la_LDFLAGS)
-libgcjgc_convenience_la_LIBADD = @addobjs@
-libgcjgc_convenience_la_DEPENDENCIES = @addobjs@
-AM_CXXFLAGS = @GC_CFLAGS@
-AM_CFLAGS = @GC_CFLAGS@
+libgcjgc_convenience_la_LIBADD = $(addobjs)
+libgcjgc_convenience_la_DEPENDENCIES = $(addobjs)
+AM_CXXFLAGS = $(GC_CFLAGS)
+AM_CFLAGS = $(GC_CFLAGS)
+AM_LDFLAGS = $(shell $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
test_ldadd = libgcjgc.la $(THREADLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
gctest_SOURCES = tests/test.c
gctest_LDADD = $(test_ldadd)
@@ -334,14 +341,6 @@ libstaticrootslib_la_LDFLAGS = -version-info 1:2:0 -no-undefined \
-rpath /nowhere -shared-libgcc
libstaticrootslib_la_DEPENDENCIES = libgcjgc_convenience.la
-LTCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile \
- $(CC) $(DEFS) $(AM_CPPFLAGS) $(CPPFLAGS) \
- $(AM_CFLAGS) $(MY_CFLAGS) $(GC_CFLAGS)
-
-LTLDFLAGS = $(shell $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
-LINK = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
- $(CC) $(AM_CFLAGS) $(MY_CFLAGS) $(LTLDFLAGS) -o $@
-
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
@@ -886,6 +885,7 @@ uninstall-am:
mostlyclean-generic mostlyclean-libtool mostlyclean-multi pdf \
pdf-am ps ps-am tags tags-recursive uninstall uninstall-am
+override CFLAGS := $(filter-out $(O0_CFLAGS), $(CFLAGS)) $(O0_CFLAGS)
.s.lo:
$(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $<
diff --git a/boehm-gc/configure b/boehm-gc/configure
index 557d30583ac..78877e50cbc 100755
--- a/boehm-gc/configure
+++ b/boehm-gc/configure
@@ -604,7 +604,7 @@ LTLIBOBJS
LIBOBJS
toolexeclibdir
toolexecdir
-MY_CFLAGS
+O0_CFLAGS
addtests
addlibs
addincludes
@@ -15332,59 +15332,40 @@ addobjs="$addobjs $machdep"
#
# Check for AViiON Machines running DGUX
#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if host is AViiON running DGUX" >&5
-$as_echo_n "checking if host is AViiON running DGUX... " >&6; }
ac_is_dgux=no
ac_fn_c_check_header_mongrel "$LINENO" "sys/dg_sys_info.h" "ac_cv_header_sys_dg_sys_info_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_dg_sys_info_h" = x""yes; then :
- ac_is_dgux=yes;
+ ac_is_dgux=yes
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if host is AViiON running DGUX" >&5
+$as_echo_n "checking if host is AViiON running DGUX... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_is_dgux" >&5
$as_echo "$ac_is_dgux" >&6; }
## :GOTCHA: we do not check anything but sys/dg_sys_info.h
if test $ac_is_dgux = yes; then
if test "$enable_full_debug" = "yes"; then
- CFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
- CXXFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
- else
- CFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
- CXXFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ GC_CFLAGS="$GC_CFLAGS -mstandard"
fi
-
-
+ GC_CFLAGS="$GC_CFLAGS -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Solaris gcc optimization fix is necessary" >&5
-$as_echo_n "checking whether Solaris gcc optimization fix is necessary... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC optimization should be disabled" >&5
+$as_echo_n "checking whether GCC optimization should be disabled... " >&6; }
+O0_CFLAGS=
case "$host" in
- *aix*)
- if test "$GCC" = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+ *aix*) test "$GCC" = yes && O0_CFLAGS=-O0 ;;
+ *) ;;
+esac
+if test x"$O0_CFLAGS" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- new_CFLAGS=
- for i in $CFLAGS; do
- case "$i" in
- -O*)
- ;;
- *)
- new_CFLAGS="$new_CFLAGS $i"
- ;;
- esac
- done
- CFLAGS="$new_CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- fi
- ;;
- *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; } ;;
-esac
-
-MY_CFLAGS="$CFLAGS"
+fi
diff --git a/boehm-gc/configure.ac b/boehm-gc/configure.ac
index 32c627524a7..43be0b4866d 100644
--- a/boehm-gc/configure.ac
+++ b/boehm-gc/configure.ac
@@ -453,54 +453,34 @@ AC_SUBST(addtests)
#
# Check for AViiON Machines running DGUX
#
-AC_MSG_CHECKING(if host is AViiON running DGUX)
ac_is_dgux=no
-AC_CHECK_HEADER(sys/dg_sys_info.h,
-[ac_is_dgux=yes;])
+AC_CHECK_HEADER(sys/dg_sys_info.h, [ac_is_dgux=yes])
+AC_MSG_CHECKING(if host is AViiON running DGUX)
AC_MSG_RESULT($ac_is_dgux)
## :GOTCHA: we do not check anything but sys/dg_sys_info.h
if test $ac_is_dgux = yes; then
if test "$enable_full_debug" = "yes"; then
- CFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
- CXXFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
- else
- CFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
- CXXFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2"
+ GC_CFLAGS="$GC_CFLAGS -mstandard"
fi
- AC_SUBST(CFLAGS)
- AC_SUBST(CXXFLAGS)
+ GC_CFLAGS="$GC_CFLAGS -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend"
fi
dnl As of 4.13a2, the collector will not properly work on Solaris when
dnl built with gcc and -O. So we remove -O in the appropriate case.
dnl Not needed anymore on Solaris.
-AC_MSG_CHECKING(whether Solaris gcc optimization fix is necessary)
+AC_MSG_CHECKING([whether GCC optimization should be disabled])
+O0_CFLAGS=
case "$host" in
- *aix*)
- if test "$GCC" = yes; then
- AC_MSG_RESULT(yes)
- new_CFLAGS=
- for i in $CFLAGS; do
- case "$i" in
- -O*)
- ;;
- *)
- new_CFLAGS="$new_CFLAGS $i"
- ;;
- esac
- done
- CFLAGS="$new_CFLAGS"
- else
- AC_MSG_RESULT(no)
- fi
- ;;
- *) AC_MSG_RESULT(no) ;;
+ *aix*) test "$GCC" = yes && O0_CFLAGS=-O0 ;;
+ *) ;;
esac
-
-dnl We need to override the top-level CFLAGS. This is how we do it.
-MY_CFLAGS="$CFLAGS"
-AC_SUBST(MY_CFLAGS)
+if test x"$O0_CFLAGS" != x; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST([O0_CFLAGS])
dnl Include defines that have become de facto standard.
dnl ALL_INTERIOR_POINTERS can be overridden in startup code.
diff --git a/boehm-gc/include/Makefile.in b/boehm-gc/include/Makefile.in
index 5f1302253ab..56c3dae6ff3 100644
--- a/boehm-gc/include/Makefile.in
+++ b/boehm-gc/include/Makefile.in
@@ -110,9 +110,9 @@ LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
-MY_CFLAGS = @MY_CFLAGS@
NM = @NM@
NMEDIT = @NMEDIT@
+O0_CFLAGS = @O0_CFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 009ba987152..0454250d398 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,422 @@
+2010-10-31 Uros Bizjak <ubizjak@gmail.com>
+
+ PR tree-optimization/46142
+ * tree-vect-stmts.c (vectorizable_call): Enlarge dt array to
+ accommodate third function argument.
+
+2010-10-30 Nathan Froyd <froydnj@codesourcery.com>
+
+ * tree-ssa-loop-im.c (rewrite_reciprocal): Use build_one_cst.
+
+2010-10-30 Nathan Froyd <froydnj@codesourcery.com>
+
+ * fold-const.c (build_zero_vector): Use build_vector_from_val.
+ * tree-vect-loop.c (get_initial_def_for_induction): Likewise.
+ (get_initial_def_for_reduction): Likewise.
+ * tree-vect-slp.c (vect_get_constant_vectors): Likewise.
+ * tree-vect-stmts.c (vect_get_vec_def_for_operand): Likewise.
+ * tree.c (build_one_cst): Likewise.
+ (build_vector_from_val): Use types_compatible_p for assert.
+
+2010-10-30 Nathan Froyd <froydnj@codesourcery.com>
+
+ * emit-rtl.c (mark_used_flags): New function.
+ (set_used_flags, reset_used_flags): Call it.
+
+2010-10-30 Uros Bizjak <ubizjak@gmail.com>
+
+ PR middle-end/44569
+ * lower-suberg.c (simplify_subreg_concatn): For VOIDmode elements,
+ determine the mode of a subreg by GET_MODE_INNER of CONCATN RTX.
+
+2010-10-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/46195
+ * config/i386/i386.c (contains_aligned_value_p): Renamed to ...
+ (ix86_compat_aligned_value_p): This.
+ (ix86_old_function_arg_boundary): Renamed to ...
+ (ix86_compat_function_arg_boundary): This. Updated.
+ (ix86_contains_aligned_value_p): New.
+ (ix86_function_arg_boundary): Align long double parameters on
+ stack to 4byte in 32bit.
+
+2010-10-30 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+ * c-parser.c (c_parser_objc_at_property_declaration): Removed
+ parsing of RID_COPIES and RID_IVAR. Updated call to
+ objc_add_property_declaration.
+ * c-typecheck.c (build_component_ref): Call
+ objc_maybe_build_component_ref instead of objc_build_setter_call.
+ Use objc_is_property_ref to improve Objective-C checks.
+ (cp_build_modify_expr): Call objc_maybe_build_modify_expr instead
+ of objc_build_getter_call.
+
+2010-10-29 Paul Koning <ni1d@arrl.net>
+
+ * doc/tm.texi.in (REGNO_OK_FOR_BASE_P, REGNO_MODE_OK_FOR_BASE_P,
+ REGNO_MODE_OK_FOR_REG_BASE, REGNO_MODE_CODE_OK_FOR_BASE_P,
+ REGNO_OK_FOR_INDEX_P): Delete non-strict variant.
+ (REG_OK_STRICT): Move description.
+
+2010-10-29 Paul Koning <ni1d@arrl.net>
+
+ * config/pdp11/pdp11.md (*and<mode>): Rename to *bic<mode>.
+
+2010-10-29 Paul Koning <ni1d@arrl.net>
+
+ * config/pdp11/pdp11.md (divhi3, modhi3, divmodhi3): Fix ICE.
+
+2010-10-29 Paul Koning <ni1d@arrl.net>
+
+ PR/41822
+ * config/pdp11/pdp11.md (andhi3, andqi3): Fix wrong code error.
+
+2010-10-29 Richard Henderson <rth@redhat.com>
+
+ PR rtl-opt/46226
+ * stmt.c (expand_asm_operands): Call do_pending_stack_adjust
+ for asm goto.
+
+2010-10-29 Paul Koning <ni1d@arrl.net>
+
+ * config/pdp11/pdp11.c (output_move_quad): Fix ICE for CPU
+ register to register move.
+
+2010-10-29 Paul Koning <ni1d@arrl.net>
+
+ * config/pdp11/pdp11.c (print_operand_address): Correct handling
+ of integer constant addresses, delete vax-only logic.
+
+2010-10-11 Hariharan Sandanagobalane <hariharan@picochip.com>
+
+ * config/picochip/picochip.c (picochip_is_short_branch): Simplify
+ a conditional expression.
+
+2010-10-29 Paul Koning <ni1d@arrl.net>
+
+ * config/pdp11/pdp11.c (pdp11_trampoline_init): Correct
+ instruction encoding.
+
+2010-10-29 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
+ Andrew Pinski <pinskia@gmail.com>
+
+ * tree.h (build_vector_from_val): Declare.
+ * tree.c (build_vector_from_val): New function.
+ * c-typeck.c (build_binary_op): Handle vector shifting.
+ * doc/extend.texi: Description of the vector shifting operation.
+
+2010-10-29 Paul Koning <pkoning@equallogic.com>
+
+ * config/pdp11/pdp11-protos.h (pdp11_cannot_change_mode_class,
+ pdp11_secondary_memory_needed): Declare.
+ * config/pdp11/predicates.md (float_operand): New predicate.
+ * config/pdp11/pdp11.md (RETVAL_REGNUM): New constant.
+ (cbranchdf4, movdf): Change predicate.
+ (movsf): Handle FPU register case.
+ (truncdfsf2, extendsfdf2): Add FPU register case.
+ * config/pdp11/pdp11.c (TARGET_SECONDARY_RELOAD,
+ TARGET_REGISTER_MOVE_COST, TARGET_PREFERRED_RELOAD_CLASS,
+ TARGET_PREFERRED_OUTPUT_RELOAD_CLASS): Define.
+ (pdp11_register_move_cost): Update cost matrix.
+ (pdp11_cannot_change_mode_class, pdp11_preferred_reload_class,
+ pdp11_preferred_output_reload_class, pdp11_secondary_reload,
+ pdp11_secondary_memory_needed): New function.
+ (pdp11_return_in_memory): Add other float types.
+ * config/pdp11/pdp11.h (HARD_REGNO_MODE_OK): Add other float types.
+ (SECONDARY_MEMORY_NEEDED, CANNOT_CHANGE_MODE_CLASS): Define.
+ (PREFERRED_RELOAD_CLASS, SECONDARY_RELOAD_CLASS,
+ REGISTER_MOVE_COST): Delete.
+ (BASE_RETURN_VALUE_REG): Add other float types.
+
+2010-10-29 Nick Clifton<nickc@redhat.com>
+
+ * doc/invoke.texi: Document -mam34 and -mtune options.
+ * config/mn10300/mn10300.c (mn10300_tune_string): New variable.
+ (mn10300_tune_cpu): New variable.
+ (mn10300_handle_option): Handle -mam34 and -mtune options.
+ (mn10300_option_override): Convert tune string into tune cpu variable.
+ (mn10300_legitimate_constant_p): Delete unused local variable.
+ (is_load_insn): New function.
+ (is_store_insn): New function.
+ (mn10300_adjust_schedule_cost): New function.
+ (TARGET_SCHED_ADJUST_COST): Define.
+ * config/mn10300/mn10300.opt (mam34): New option.
+ (mtune): New option.
+ * config/mn10300/mn10300.h (TARGET_CPU_CPP_BUILTINS): Add AM34 support.
+ (enum processor_type): Add AM34.
+ (TARGET_AM34): Define.
+ * config/mn10300/mn10300.md (attr cpu): Add am34.
+ Add pipeline description.
+ (movqi, movhi, movsi, movsf, movdf, movdi): Fix predicates.
+ Remove unneeded alternatives. Add timing attribute.
+ (pop_pic_reg, am33_addsi3, mn10300_addsi3, am33_subsi3,
+ mn10300_subsi3, mulsidi3, umulsidi3, am33_mulsi3,
+ mn10300_mulsi3, udivmodsi4_am33, divmodsi4, am33_andsi3,
+ mn10300_andsi3, am33_iorsi3, mn10300_iorsi3, am33_xorsi3,
+ mn10300_xorsi3, byte_clear, byte_set, bit_clear1, bit_clear2,
+ bit_set, am33_iorqi3, mn10300_iorqi3, test_byte_bitfield,
+ bit_test, subreg_bit_test, cmpsi, am33_cmpsf, am33_subsi3,
+ float_conditional_branch, jump, indirect_jump, tablejump,
+ call_internal, call_value_internal, zero_extendqisi2_am33,
+ zero_extendqisi2_mn10300, zero_extendhisi2_am33,
+ zero_extendhisi2_mn10300, extendqisi2_am33, extendqisi2_mn10300,
+ extendhisi2_am33, extendhisi2_mn10300, am33_ashlsi3,
+ mn10300_ashlsi3, am33_lshrsi3, mn10300_lshrsi3, am33_ashrisi3,
+ mn10300_ashrsi3, abssf2_am33_2, negsf2_am33_2, rsqrtsf2,
+ addsf3_internal, subsf3_internal, mulsf3_internal, divsf3,
+ fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4, return_internal,
+ return_internal_regs, store_movm, return, call_next_insn):
+ Add timing attribute.
+ (am33_subsi3): Add missing clobber of CC_REG.
+ (am33_andsi3, mn10300_andsi3): Fix compile time warnings.
+ (udivmodsi4, udivmodsi4_insn, divmodsi4, test_byte_bitfield,
+ subreg_bit_test, zero_extendqisi2, zero_extendhisi2,
+ extendqisi2): Fix predicates.
+ (call_internal, call_internal_value): Separate alternatives.
+ * config/mn10300/t-mn10300: Add AM34 multilib.
+
+2010-10-29 Paolo Bonzini <bonzini@gnu.org>
+
+ * config/sh/sh.c (sh_promote_function_mode): Use
+ default_promote_function_mode if !sh_promote_prototypes.
+
+2010-10-28 Paolo Bonzini <bonzini@gnu.org>
+
+ * recog.c (split_all_insns): Remove dead code.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/microblaze/microblaze-protos.h (function_arg): Delete.
+ (function_arg_advance): Delete.
+ * config/microblaze/microblaze.h (FUNCTION_ARG_ADVANCE): Delete.
+ (FUNCTION_ARG): Delete.
+ * config/microblaze/microblaze.c (function_arg_advance): Rename to...
+ (microblaze_function_arg_advance): ...this. Make static. Take a
+ const_tree and a bool.
+ (function-arg): Rename to...
+ (microblaze_function_arg): ...this. Make static. Take a const_tree
+ and a bool.
+ (microblaze_expand_prologue): Call targetm.calls.function_arg and
+ targetm.calls.function_arg_advance.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * score.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/cris/cris.h (FUNCTION_ARG, FUNCTION_INCOMING_ARG): Delete.
+ (FUNCTION_ARG_ADVANCE): Delete.
+ * config/cris/cris.c (cris_function_arg_1, cris_function_arg): New
+ functions.
+ (cris_function_incoming_arg, cris_function_arg_advance): New functions.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_INCOMING_ARG): Define.
+ (TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/lm32/lm32-protos.h (lm32_function_arg): Delete.
+ * config/lm32/lm32.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+ * config/mcore/mcore.c (mcore_function_arg): Declare. Make static.
+ Take a const_tree and a bool.
+ (mcore_function_arg_advance): New function.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/mcore/mcore-protos.h (mcore_function_arg): Delete.
+ * config/mcore/mcore.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+ * config/mcore/mcore.c (mcore_function_arg): Declare. Make static.
+ Take a const_tree and a bool.
+ (mcore_function_arg_advance): New function.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/h8300/h8300-protos.h (function_arg): Delete.
+ * config/h8300/h8300.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+ * config/h8300/h8300.c (function_arg): Rename to...
+ (h8300_function_arg): ...this. Make static. Take a const_tree and
+ a bool.
+ (h8300_function_arg_advance): New function.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/arc/arc.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Move code
+ to...
+ * config/arc/arc.c (arc_function_arg): ...here and...
+ (arc_function_arg_advance): ...here. New functions.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/crx/crx-protos.h (crx_function_arg): Delete.
+ (crx_function_arg_advance): Delete.
+ * config/crx/crx.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+ * config/crx/crx.c (crx_function_arg): Make static. Take a
+ const_tree and a bool.
+ (crx_function_arg_advance): Make static. Take a const_tree and a bool.
+ (enough_regs_for_param): Take a const_tree.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/m68hc11/m68hc11-protos.h (m68hc11_function_arg): Delete.
+ (m68hc11_function_arg_advance): Delete.
+ * config/m68hc11/m68hc11.h (FUNCTION_ARG): Delete.
+ (FUNCTION_ARG_ADVANCE): Delete.
+ * config/m68hc11/m68hc11.c (m68hc11_function_arg): Make static.
+ Take a const_tree and a bool.
+ (m68hc11_function_arg_advance): Likewise.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/stormy16/stormy16-protos.h (xstormy16_function_arg): Delete.
+ (xstormy16_function_arg_advance): Delete.
+ * config/stormy16/stormy16.h (FUNCTION_ARG): Delete.
+ (FUNCTION_ARG_ADVANCE): Delete.
+ * config/stormy16/stormy16.c (xstormy16_function_arg): Make static.
+ Take a const_tree and a bool.
+ (xstormy16_function_arg_advance): Likewise. Return void, updating
+ the CUM parameter instead.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/moxie/moxie-protos.h (moxie_function_arg): Delete.
+ * config/moxie/moxie.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+ (MOXIE_FUNCTION_ARG_SIZE): Move to...
+ * config/moxie/moxie.c (MOXIE_FUNCTION_ARG_SIZE): ...here.
+ (moxie_function_arg): Make static. Take a const_tree and a bool.
+ (moxie_function_arg_advance): New function.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/mn10300/mn10300-protos.h (function_arg): Delete.
+ * config/mn10300/mn10300.h (FUNCTION_ARG): Delete.
+ (FUNCTION_ARG_ADVANCE): Delete.
+ * config/mn10300/mn10300.c (function_arg): Rename to...
+ (mn10300_function_arg): ...this. Make static. Take a const_tree
+ and a bool.
+ (mn10300_function_arg_advance): New function.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/iq2000/iq2000-protos.h (function_arg): Delete.
+ (function_arg_advance): Delete.
+ * config/iq2000/iq2000.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+ * config/iq2000/iq2000.c (function_arg): Rename to...
+ (iq2000_function_arg): ...this. Make static. Take a const_tree and
+ a bool.
+ (function_arg_advance): Rename to...
+ (iq2000_function_arg_advance): ...this. Make static. Take a
+ const_tree and a bool.
+ (iq2000_expand_prologue): Call iq2000_function_arg_advance and
+ iq2000_function_arg.
+ (iq2000_pass_by_reference): Call iq2000_function_arg).
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/fr30/fr30-protos.h (fr30_num_arg_regs): Delete.
+ * config/fr30/fr30.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+ * config/fr30/fr30.c (fr30_num_arg_regs): Make static. Take a
+ const_tree.
+ (fr30_function_arg): New function.
+ (fr30_function_arg_advance): New function.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/frv/frv-protos.h (frv_function_arg): Delete.
+ (frv_function_arg_advance): Delete.
+ * config/frv/frv.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Delete.
+ * config/frv/frv.c (frv_function_arg): Rename to...
+ (frv_function_arg_1): Make static. Take const_tree and bool arguments.
+ (frv_function_arg, frv_function_incoming_arg): New functions.
+ (frv_function_arg_advance): Make static. Take a const_tree and a bool.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_INCOMING_ARG): Define.
+ (TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-28 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/46153
+ * config/i386/sse.md (sse_movhlps_exp): Use destination
+ returned from ix86_fixup_binary_operands to expand insn.
+ (sse_movlhps_exp): Ditto.
+ (sse_loadhps_exp): Ditto.
+ (sse_loadlps_exp): Ditto.
+ (sse2_loadhpd_exp): Ditto.
+ (sse2_loadlpd_exp): Ditto.
+
+2010-10-28 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/arm/arm.c (const_ok_for_arm): Support 0xXY00XY00 pattern
+ constants in thumb2.
+
+2010-10-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * combine.c (set_nonzero_bits_and_sign_copies): Use unsigned
+ arithmetics in masking operations.
+ (contains_muldiv): Likewise.
+ (try_combine): Likewise.
+ (find_split_point): Likewise.
+ (combine_simplify_rtx): Likewise.
+ (simplify_if_then_else): Likewise.
+ (simplify_set): Likewise.
+ (expand_compound_operation): Likewise.
+ (expand_field_assignment): Likewise.
+ (make_extraction): Likewise.
+ (extract_left_shift): Likewise.
+ (make_compound_operation): Likewise.
+ (force_to_mode): Likewise.
+ (make_field_assignment): Likewise.
+ (reg_nonzero_bits_for_combine): Likewise.
+ (simplify_shift_const_1): Likewise.
+ (simplify_comparison): Likewise.
+
+2010-10-27 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/ia64/ia64-protos.h (ia64_function_arg): Delete.
+ (ia64_function_arg_advance): Delete.
+ * config/ia64/ia64.h (FUNCTION_ARG, FUNCTION_INCOMING_ARG): Delete.
+ (FUNCTION_ARG_ADVANCE): Delete.
+ * config/ia64/ia64.c (ia64_function_arg): Rename to...
+ (ia64_function_arg_1): ...this. Make static. Take const_tree and
+ bool arguments.
+ (ia64_function_arg, ia64_function_incoming_arg): New functions.
+ (ia64_function_arg_advance): Make static. Take a const_tree and
+ a bool.
+ (TARGET_FUNCTION_ARG, TARGET_FUNCTION_INCOMING_ARG): Define.
+ (TARGET_FUNCTION_ARG_ADVANCE): Define.
+
+2010-10-27 Steve Ellcey <sje@cup.hp.com>
+
+ * doc/tm.texi.in (TARGET_GET_RAW_RESULT_MODE): New.
+ (TARGET_GET_RAW_ARG_MODE): New.
+ * doc/tm.texi: Regenerate.
+ * target.def (get_raw_result_mode): New.
+ (get_raw_arg_mode): New.
+ * targhooks.c (default_get_reg_raw_mode): New.
+ * targhooks.h (default_get_reg_raw_mode): New.
+ * builtins.c (apply_args_size): Use targetm.calls.get_raw_arg_mode.
+ (apply_result_size): Ditto.
+ * config/ia64/ia64.c (ia64_get_reg_raw_mode): New.
+ (TARGET_GET_RAW_RESULT_MODE): Define.
+ (TARGET_GET_RAW_ARG_MODE): Ditto.
+
+2010-10-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sol2-unwind.h (sparc64_fallback_frame_state): Adjust
+ for newer Solaris 10 release.
+ (sparc_fallback_frame_state): Likewise.
+
2010-10-27 Jason Merrill <jason@redhat.com>
* gimplify.c (gimplify_decl_expr): Handle anonymous artificial
@@ -42,8 +461,7 @@
caller_pass_avx256_p based on argument type.
(ix86_expand_epilogue): Emit vzeroupper if 256bit AVX register
is used, but not returned by caller.
- (ix86_expand_call): Emit vzeroupper if 256bit AVX register is
- used.
+ (ix86_expand_call): Emit vzeroupper if 256bit AVX register is used.
(ix86_local_alignment): Set use_avx256_p if 256bit AVX register
is used.
(ix86_minimum_alignment): Likewise.
@@ -74,7 +492,7 @@
* config/i386/t-mingw-w64 (SHLIB_LC): Likewise.
2010-10-27 Eric Botcazou <ebotcazou@adacore.com>
- Olivier Hainque <hainque@adacore.com>
+ Olivier Hainque <hainque@adacore.com>
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Fix regnum
of EBP. Do not restore reg #9. Remove +1 adjustment to EIP and set
@@ -82,6 +500,11 @@
2010-10-27 Nicola Pero <nicola.pero@meta-innovation.com>
+ * c-parser.c (cp_parser_objc_at_property_declaration): Removed
+ parsing of RID_COPIES and RID_IVAR.
+
+2010-10-27 Nicola Pero <nicola.pero@meta-innovation.com>
+
* c-parser.c (c_parser_objc_at_property_declaration): Recognize
RID_ASSIGN, RID_COPY, RID_RETAIN, RID_READWRITE and RID_NONATOMIC.
Do not use objc_set_property_attr, but use local variables
@@ -103,11 +526,10 @@
c_parser_objc_at_property, now
c_parser_objc_at_property_declaration.
(c_parser_objc_methodprotolist): Same change.
-
+
2010-10-26 H.J. Lu <hongjiu.lu@intel.com>
- * config/i386/i386.md (split_stack_return): Put back
- unspec_volatile.
+ * config/i386/i386.md (split_stack_return): Put back unspec_volatile.
2010-10-26 Jan Hubicka <jh@suse.cz>
@@ -118,7 +540,8 @@
2010-10-26 Jan Hubicka <jh@suse.cz>
- * cgraphbuild.c (build_cgraph_edges): Use ipa-reference to represent OMP.
+ * cgraphbuild.c (build_cgraph_edges): Use ipa-reference
+ to represent OMP.
2010-10-26 H.J. Lu <hongjiu.lu@intel.com>
@@ -151,31 +574,33 @@
(cgraph_can_remove_if_no_direct_calls_and_refs): Do not try
to optimize away static ctors/dtors; it does not work on inline clones;
external functions can always be rmeoved.
- (cgraph_will_be_removed_from_program_if_no_direct_calls): Assert on inline
- clones; in LTO external functions always can go.
+ (cgraph_will_be_removed_from_program_if_no_direct_calls): Assert on
+ inline clones; in LTO external functions always can go.
(cgraph_used_from_object_file_p): Handle EXTERNAL functions correctly.
- (cgraph_mark_address_taken_node): Assert that we are not taking address of
- inline clone.
+ (cgraph_mark_address_taken_node): Assert that we are not taking
+ address of inline clone.
(cgraph_can_remove_if_no_direct_calls_p): We always eventually remove
external functions.
- * ipa-cp.c (ipcp_cloning_candidate_p): Do not clone functions with address taken.
- (ipcp_initialize_node_lattices): Only local functions can be handled without cloning.
+ * ipa-cp.c (ipcp_cloning_candidate_p): Do not clone functions with
+ address taken.
+ (ipcp_initialize_node_lattices): Only local functions can be
+ handled without cloning.
* cgraph.h (cgraph_set_readonly_flag,
cgraph_set_looping_const_or_pure_flag): Remove.
(cgraph_set_const_flag): Declare.
(cgraph_set_pure_flag): Update.
* ipa-pure-const (propagate_pure_const, local_pure_const): Update
flags setting code.
- * ipa.c (cgraph_remove_unreachable_nodes): Fix formating; do not look at inline
- clones; fix handling of external definitions.
+ * ipa.c (cgraph_remove_unreachable_nodes): Fix formating; do not
+ look at inline clones; fix handling of external definitions.
(cgraph_postorder): Do not look at inline clones in the first pass.
(function_and_variable_visibility): Drop constructors/destructor
flags at pure and const functions.
* tree-profile.c (tree_profiling): Update.
* ipa-inline.c (cgraph_clone_inlined_nodes): Always clone functions with
address taken; external functions do not account to whole program size.
- (cgraph_decide_inlining): Likewise; do not try to inline functions already
- inlined.
+ (cgraph_decide_inlining): Likewise; do not try to inline
+ functions already inlined.
2010-10-26 Jie Zhang <jie@codesourcery.com>
@@ -198,7 +623,7 @@
PR target/44948
* config/i386/i386.c (ix86_old_function_arg_boundary): New.
(ix86_function_arg_boundary): Always align parameters on stack
- in 64bit and align parameters with alignment >= 16byte on stack
+ in 64bit and align parameters with alignment >= 16byte on stack
in 32bit. Warn alignment change.
2010-10-26 Ian Lance Taylor <iant@google.com>
@@ -207,7 +632,7 @@
* ipa-prop.c (ipa_modify_call_arguments): Correct type of MEM_REF
offset.
-2010-10-25 Rodrigo Rivas Costa <rodrigorivascosta@gmail.com>
+2010-10-25 Rodrigo Rivas Costa <rodrigorivascosta@gmail.com>
Implement opaque-enum-specifiesr for C++0x
* tree.h (ENUM_IS_OPAQUE): New.
@@ -216,8 +641,7 @@
2010-10-26 Jie Zhang <jie@codesourcery.com>
* stor-layout.c (layout_decl): Use the field's type to
- determine the mode and keep DECL_BIT_FIELD for a volatile
- bit-field.
+ determine the mode and keep DECL_BIT_FIELD for a volatile bit-field.
* config/arm/arm.c (arm_override_options): Default to
-fstrict-volatile-bitfields.
@@ -228,10 +652,6 @@
* config/pdp11/pdp11.c: Use named constants instead of numbers.
* config/pdp11.pdp11.h: Ditto.
-2010-10-25 Changpeng Fang <changpeng.fang@amd.com>
-
- * Changelog (2010-10-22 Changpeng Fang): Correct the Changelog entries.
-
2010-10-25 Eric Botcazou <ebotcazou@adacore.com>
* configure.ac: Use $cpu_type instead of $target to define the nop.
@@ -261,8 +681,7 @@
2010-10-24 Ian Lance Taylor <iant@google.com>
- * config/i386/i386.c (ix86_va_start): Remove extraneous blank
- line.
+ * config/i386/i386.c (ix86_va_start): Remove extraneous blank line.
2010-10-24 Eric Botcazou <ebotcazou@adacore.com>
@@ -276,8 +695,7 @@
* gcc.c (n_switches_alloc_debug_check): New.
(set_option_handlers): New.
(process_command): Use set_option_handlers.
- (do_self_spec): Pass spec-generated options through option
- handlers.
+ (do_self_spec): Pass spec-generated options through option handlers.
(main): Also save and restore n_switches_alloc when swapping
switch arrays.
@@ -337,7 +755,7 @@
(TARGET_SCHED_REORDER2): Define to mips_sched_reorder2
instead of mips_sched_reorder.
- Revert
+ Revert:
2008-09-09 Andrey Belevantsev <abel@ispras.ru>
PR rtl-optimization/37360
* haifa-sched.c (max_issue): Do not assert that we never issue more
@@ -370,8 +788,7 @@
(m32c_addr_space_subset_p): New.
(m32c_addr_space_convert): New.
(conversions): Add __far operand patterns.
- (m32c_prepare_move): Force constants into registers for __far
- moves.
+ (m32c_prepare_move): Force constants into registers for __far moves.
(m32c_split_move): __far moves are always split.
* config/m32c/addsub.md (addsi3_1): Support SImode symbols.
* config/m32c/mov.md (mov<mode>_far_op1): New.
@@ -380,8 +797,8 @@
(movhi_op): Likewise.
(movsi_splittable): Split A1A0 also.
-2010-10-22 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
- Andrew Pinski <pinskia@gmail.com>
+2010-10-22 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
+ Andrew Pinski <pinskia@gmail.com>
* c-typeck.c (build_array_ref): Handle subscripting of vectors.
* doc/extend.texi: New paragraph
@@ -414,8 +831,7 @@
* gcc.c (DEFAULT_SWITCH_CURTAILS_COMPILATION,
SWITCH_CURTAILS_COMPILATION): Remove.
- * doc/tm.texi.in (SWITCH_CURTAILS_COMPILATION): Remove
- documentation.
+ * doc/tm.texi.in (SWITCH_CURTAILS_COMPILATION): Remove documentation.
* doc/tm.texi: Regenerate.
* system.h (SWITCH_CURTAILS_COMPILATION): Poison.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 3ca7bd6bf73..d227da1eaf0 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20101027
+20101031
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 2f3fac855fc..1d27923619d 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,11 @@
+2010-10-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (gigi): Fix formatting issues.
+ (build_raise_check): Likewise.
+ (gnat_to_gnu): Likewise.
+ * gcc-interface/utils2.c (build_call_raise_range): Likewise.
+ (build_call_raise_column): Likewise.
+
2010-10-26 Robert Dewar <dewar@adacore.com>
* exp_ch5.adb, exp_prag.adb, sem_ch3.adb, exp_atag.adb, layout.adb,
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index f130439d7c3..39dc0284d11 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -469,13 +469,12 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
integer_type_node,
t))),
NULL_TREE, false, true, true, NULL, Empty);
-
- for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++)
- gnat_raise_decls[i] = decl;
TREE_THIS_VOLATILE (decl) = 1;
TREE_SIDE_EFFECTS (decl) = 1;
TREE_TYPE (decl)
= build_qualified_type (TREE_TYPE (decl), TYPE_QUAL_VOLATILE);
+ for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++)
+ gnat_raise_decls[i] = decl;
}
else
{
@@ -647,37 +646,42 @@ build_raise_check (int check, tree void_tree, enum exception_info_kind kind)
if (kind != exception_simple)
{
sprintf (name, "__gnat_rcheck_%.2d_ext", check);
- result = create_subprog_decl
- (get_identifier (name), NULL_TREE,
- build_function_type
+ result
+ = create_subprog_decl
+ (get_identifier (name), NULL_TREE,
+ build_function_type
(void_type_node,
tree_cons
- (NULL_TREE,
- build_pointer_type (unsigned_char_type_node),
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- kind == exception_column ? void_tree :
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, integer_type_node, void_tree)))))),
- NULL_TREE, false, true, true, NULL, Empty);
+ (NULL_TREE, build_pointer_type (unsigned_char_type_node),
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ kind == exception_column
+ ? void_tree
+ : tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE,
+ integer_type_node,
+ void_tree)))))),
+ NULL_TREE, false, true, true, NULL, Empty);
}
else
{
sprintf (name, "__gnat_rcheck_%.2d", check);
- result = create_subprog_decl
- (get_identifier (name), NULL_TREE,
- build_function_type
+ result
+ = create_subprog_decl
+ (get_identifier (name), NULL_TREE,
+ build_function_type
(void_type_node,
tree_cons
- (NULL_TREE,
- build_pointer_type (unsigned_char_type_node),
- tree_cons (NULL_TREE, integer_type_node, void_tree))),
- NULL_TREE, false, true, true, NULL, Empty);
+ (NULL_TREE, build_pointer_type (unsigned_char_type_node),
+ tree_cons (NULL_TREE, integer_type_node, void_tree))),
+ NULL_TREE, false, true, true, NULL, Empty);
}
+
TREE_THIS_VOLATILE (result) = 1;
TREE_SIDE_EFFECTS (result) = 1;
TREE_TYPE (result)
= build_qualified_type (TREE_TYPE (result), TYPE_QUAL_VOLATILE);
+
return result;
}
@@ -5602,8 +5606,8 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Raise_Program_Error:
case N_Raise_Storage_Error:
{
- int reason = UI_To_Int (Reason (gnat_node));
- Node_Id cond = Condition (gnat_node);
+ const int reason = UI_To_Int (Reason (gnat_node));
+ const Node_Id cond = Condition (gnat_node);
bool handled = false;
if (type_annotate_only)
@@ -5622,8 +5626,8 @@ gnat_to_gnu (Node_Id gnat_node)
{
if (reason == CE_Access_Check_Failed)
{
- handled = true;
gnu_result = build_call_raise_column (reason, gnat_node);
+ handled = true;
}
else if ((reason == CE_Index_Check_Failed
|| reason == CE_Range_Check_Failed
@@ -5640,12 +5644,14 @@ gnat_to_gnu (Node_Id gnat_node)
&& Known_Esize (type)
&& UI_To_Int (Esize (type)) <= 32)
{
+ Node_Id right_op = Right_Opnd (op);
+ gnu_result
+ = build_call_raise_range
+ (reason, gnat_node,
+ gnat_to_gnu (index), /* index */
+ gnat_to_gnu (Low_Bound (right_op)), /* first */
+ gnat_to_gnu (High_Bound (right_op))); /* last */
handled = true;
- gnu_result = build_call_raise_range
- (reason, gnat_node,
- gnat_to_gnu (index), /* index */
- gnat_to_gnu (Low_Bound (Right_Opnd (op))), /* first */
- gnat_to_gnu (High_Bound (Right_Opnd (op)))); /* last */
}
}
}
@@ -5654,20 +5660,18 @@ gnat_to_gnu (Node_Id gnat_node)
{
set_expr_location_from_node (gnu_result, gnat_node);
gnu_result = build3 (COND_EXPR, void_type_node,
- gnat_to_gnu (cond),
+ gnat_to_gnu (cond),
gnu_result, alloc_stmt_list ());
}
else
{
gnu_result = build_call_raise (reason, gnat_node, kind);
- /* If the type is VOID, this is a statement, so we need to
- generate the code for the call. Handle a Condition, if there
- is one. */
+ /* If the type is VOID, this is a statement, so we need to generate
+ the code for the call. Handle a Condition, if there is one. */
if (TREE_CODE (gnu_result_type) == VOID_TYPE)
{
set_expr_location_from_node (gnu_result, gnat_node);
-
if (Present (cond))
gnu_result = build3 (COND_EXPR, void_type_node,
gnat_to_gnu (cond),
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 0671308369f..8088d53a1b0 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -1590,8 +1590,8 @@ build_call_raise_range (int msg, Node_Id gnat_node,
build_index_type (size_int (len)));
call = build_call_nary (TREE_TYPE (TREE_TYPE (fndecl)),
- build_unary_op (ADDR_EXPR, NULL_TREE, fndecl),
- 6,
+ build_unary_op (ADDR_EXPR, NULL_TREE, fndecl),
+ 6,
build1 (ADDR_EXPR,
build_pointer_type (unsigned_char_type_node),
filename),
@@ -1644,8 +1644,8 @@ build_call_raise_column (int msg, Node_Id gnat_node)
build_index_type (size_int (len)));
call = build_call_nary (TREE_TYPE (TREE_TYPE (fndecl)),
- build_unary_op (ADDR_EXPR, NULL_TREE, fndecl),
- 3,
+ build_unary_op (ADDR_EXPR, NULL_TREE, fndecl),
+ 3,
build1 (ADDR_EXPR,
build_pointer_type (unsigned_char_type_node),
filename),
diff --git a/gcc/builtins.c b/gcc/builtins.c
index ca69efa10d7..611b777ec9c 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1334,7 +1334,7 @@ apply_args_size (void)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (FUNCTION_ARG_REGNO_P (regno))
{
- mode = reg_raw_mode[regno];
+ mode = targetm.calls.get_raw_arg_mode (regno);
gcc_assert (mode != VOIDmode);
@@ -1370,7 +1370,7 @@ apply_result_size (void)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (targetm.calls.function_value_regno_p (regno))
{
- mode = reg_raw_mode[regno];
+ mode = targetm.calls.get_raw_result_mode (regno);
gcc_assert (mode != VOIDmode);
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index ce19bd1eb6a..761ff6b1199 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,36 @@
+2010-10-30 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+ * c-common.h (enum rid): Removed RID_COPIES and RID_IVAR.
+ (objc_add_property_declaration): Removed arguments for copies and
+ ivar.
+ (objc_build_getter_call): Renamed to
+ objc_maybe_build_component_ref.
+ (objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
+ (objc_is_property_ref): New.
+ * c-common.c (c_common_reswords): Removed copies and ivar.
+ * stub-objc.c (objc_add_property_declaration): Removed arguments
+ for copies and ivar.
+ (objc_build_getter_call): Renamed to
+ objc_maybe_build_component_ref.
+ (objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
+ (objc_is_property_ref): New.
+
+2010-10-29 Arnaud Charlet <charlet@adacore.com>
+ Matthew Gingell <gingell@adacore.com>
+
+ * c-ada-spec.c (separate_class_package): New function.
+ (pp_ada_tree_identifier): Prefix references to C++ classes with the
+ name of their enclosing package.
+ (print_ada_declaration): Use separate_class_package.
+
+2010-10-27 Jason Merrill <jason@redhat.com>
+
+ * c-common.c (c_common_reswords): Add __is_literal_type.
+ * c-common.h (enum rid): Add RID_IS_LITERAL_TYPE.
+
+ * c-common.c (check_case_value): Remove special C++ code.
+
2010-10-27 Nicola Pero <nicola.pero@meta-innovation.com>
* c-common.h (enum rid): Added RID_READWRITE, RID_ASSIGN,
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index d8910a8d787..455151a7f51 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -51,6 +51,7 @@ static void dump_ada_withs (FILE *);
static void dump_ads (const char *, void (*)(const char *),
int (*)(tree, cpp_operation));
static char *to_ada_name (const char *, int *);
+static bool separate_class_package (tree);
#define LOCATION_COL(LOC) ((expand_location (LOC)).column)
@@ -1152,6 +1153,23 @@ to_ada_name (const char *name, int *space_found)
return s;
}
+/* Return true if DECL refers to a C++ class type for which a
+ separate enclosing package has been or should be generated. */
+
+static bool
+separate_class_package (tree decl)
+{
+ if (decl)
+ {
+ tree type = TREE_TYPE (decl);
+ return type
+ && TREE_CODE (type) == RECORD_TYPE
+ && (TYPE_METHODS (type) || has_static_fields (type));
+ }
+ else
+ return false;
+}
+
static bool package_prefix = true;
/* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
@@ -1209,7 +1227,15 @@ pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
default:
break;
}
- }
+
+ if (separate_class_package (decl))
+ {
+ pp_string (buffer, "Class_");
+ pp_string (buffer, s);
+ pp_string (buffer, ".");
+ }
+
+ }
}
}
@@ -2607,8 +2633,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
{
dump_nested_types (buffer, t, t, false, cpp_check, spc);
- if (TYPE_METHODS (TREE_TYPE (t))
- || has_static_fields (TREE_TYPE (t)))
+ if (separate_class_package (t))
{
is_class = true;
pp_string (buffer, "package Class_");
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 3cdc6631d43..1b76d743861 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -565,9 +565,6 @@ const struct c_common_resword c_common_reswords[] =
{ "readwrite", RID_READWRITE, D_OBJC },
{ "retain", RID_RETAIN, D_OBJC },
{ "setter", RID_SETTER, D_OBJC },
- /* The following two will be removed once @synthesize is fully implemented. */
- { "copies", RID_COPIES, D_OBJC },
- { "ivar", RID_IVAR, D_OBJC },
};
const unsigned int num_c_common_reswords =
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index f2c69585706..7a04d10e897 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -85,9 +85,6 @@ enum rid
RID_GETTER, RID_SETTER,
RID_READONLY, RID_READWRITE,
RID_ASSIGN, RID_RETAIN, RID_COPY,
- /* RID_IVAR and RID_COPIES will be removed once @synthesize is
- completed. */
- RID_COPIES, RID_IVAR,
RID_NONATOMIC,
/* C (reserved and imaginary types not implemented, so any use is a
@@ -1038,13 +1035,13 @@ extern void objc_set_method_opt (bool);
extern void objc_finish_foreach_loop (location_t, tree, tree, tree, tree, tree);
extern bool objc_method_decl (enum tree_code);
extern void objc_add_property_declaration (location_t, tree, bool, bool, bool,
- bool, bool, bool, tree, tree,
- bool, tree);
-extern tree objc_build_getter_call (tree, tree);
-extern tree objc_build_setter_call (tree, tree);
+ bool, bool, bool, tree, tree);
+extern tree objc_maybe_build_component_ref (tree, tree);
+extern tree objc_maybe_build_modify_expr (tree, tree);
extern void objc_add_synthesize_declaration (location_t, tree);
extern void objc_add_dynamic_declaration (location_t, tree);
extern const char * objc_maybe_printable_name (tree, int);
+extern bool objc_is_property_ref (tree);
/* The following are provided by the C and C++ front-ends, and called by
ObjC/ObjC++. */
diff --git a/gcc/c-family/stub-objc.c b/gcc/c-family/stub-objc.c
index d4a4e58785a..52ecc990250 100644
--- a/gcc/c-family/stub-objc.c
+++ b/gcc/c-family/stub-objc.c
@@ -333,20 +333,24 @@ objc_add_property_declaration (location_t ARG_UNUSED (location),
bool ARG_UNUSED (parsed_property_copy),
bool ARG_UNUSED (parsed_property_nonatomic),
tree ARG_UNUSED (parsed_property_getter_ident),
- tree ARG_UNUSED (parsed_property_setter_ident),
- bool ARG_UNUSED (parsed_property_copies),
- tree ARG_UNUSED (parsed_property_ivar_ident))
+ tree ARG_UNUSED (parsed_property_setter_ident))
{
}
+bool
+objc_is_property_ref (tree ARG_UNUSED (node))
+{
+ return 0;
+}
+
tree
-objc_build_getter_call (tree ARG_UNUSED (datum), tree ARG_UNUSED (component))
+objc_maybe_build_component_ref (tree ARG_UNUSED (datum), tree ARG_UNUSED (component))
{
return 0;
}
tree
-objc_build_setter_call (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs))
+objc_maybe_build_modify_expr (tree ARG_UNUSED (lhs), tree ARG_UNUSED (rhs))
{
return 0;
}
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 932ab31e649..0e56b1898ca 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -7623,10 +7623,6 @@ c_parser_objc_at_property_declaration (c_parser *parser)
bool property_readwrite = false;
bool property_retain = false;
tree property_setter_ident = NULL_TREE;
- /* The following two will be removed once @synthesize is
- implemented. */
- bool property_copies = false;
- tree property_ivar_ident = NULL_TREE;
/* 'properties' is the list of properties that we read. Usually a
single one, but maybe more (eg, in "@property int a, b, c;" there
@@ -7670,7 +7666,6 @@ c_parser_objc_at_property_declaration (c_parser *parser)
switch (keyword)
{
case RID_ASSIGN: property_assign = true; break;
- case RID_COPIES: property_copies = true; break;
case RID_COPY: property_copy = true; break;
case RID_NONATOMIC: property_nonatomic = true; break;
case RID_READONLY: property_readonly = true; break;
@@ -7679,11 +7674,10 @@ c_parser_objc_at_property_declaration (c_parser *parser)
case RID_GETTER:
case RID_SETTER:
- case RID_IVAR:
if (c_parser_next_token_is_not (parser, CPP_EQ))
{
c_parser_error (parser,
- "getter/setter/ivar attribute must be followed by %<=%>");
+ "getter/setter attribute must be followed by %<=%>");
syntax_error = true;
break;
}
@@ -7706,7 +7700,7 @@ c_parser_objc_at_property_declaration (c_parser *parser)
else
c_parser_consume_token (parser);
}
- else if (keyword == RID_GETTER)
+ else
{
if (property_getter_ident != NULL_TREE)
c_parser_error (parser, "the %<getter%> attribute may only be specified once");
@@ -7714,14 +7708,6 @@ c_parser_objc_at_property_declaration (c_parser *parser)
property_getter_ident = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
}
- else /* RID_IVAR, this case will go away. */
- {
- if (property_ivar_ident != NULL_TREE)
- c_parser_error (parser, "the %<ivar%> attribute may only be specified once");
- else
- property_ivar_ident = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
break;
default:
c_parser_error (parser, "unknown property attribute");
@@ -7763,9 +7749,7 @@ c_parser_objc_at_property_declaration (c_parser *parser)
property_readonly, property_readwrite,
property_assign, property_retain,
property_copy, property_nonatomic,
- property_getter_ident, property_setter_ident,
- /* The following two will be removed. */
- property_copies, property_ivar_ident);
+ property_getter_ident, property_setter_ident);
}
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 1476b6d4ffc..4c53ef06d60 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -2130,8 +2130,9 @@ build_component_ref (location_t loc, tree datum, tree component)
if (!objc_is_public (datum, component))
return error_mark_node;
+ /* Detect Objective-C property syntax object.property. */
if (c_dialect_objc ()
- && (ref = objc_build_getter_call (datum, component)))
+ && (ref = objc_maybe_build_component_ref (datum, component)))
return ref;
/* See if there is a field or component with name COMPONENT. */
@@ -4869,8 +4870,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
return error_mark_node;
- /* For ObjC, defer this check until we have assessed CLASS.property. */
- if (!c_dialect_objc () && !lvalue_or_else (lhs, lv_assign))
+ /* For ObjC properties, defer this check. */
+ if (!objc_is_property_ref (lhs) && !lvalue_or_else (lhs, lv_assign))
return error_mark_node;
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
@@ -4913,9 +4914,13 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
if (c_dialect_objc ())
{
- result = objc_build_setter_call (lhs, newrhs);
+ /* Check if we are modifying an Objective-C property reference;
+ if so, we need to generate setter calls. */
+ result = objc_maybe_build_modify_expr (lhs, newrhs);
if (result)
return result;
+
+ /* Else, do the check that we postponed for Objective-C. */
if (!lvalue_or_else (lhs, lv_assign))
return error_mark_node;
}
@@ -9727,7 +9732,21 @@ build_binary_op (location_t location, enum tree_code code,
Also set SHORT_SHIFT if shifting rightward. */
case RSHIFT_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+ if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+ && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
&& code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST)
@@ -9754,9 +9773,10 @@ build_binary_op (location_t location, enum tree_code code,
/* Use the type of the value to be shifted. */
result_type = type0;
- /* Convert the shift-count to an integer, regardless of size
- of value being shifted. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+ /* Convert the non vector shift-count to an integer, regardless
+ of size of value being shifted. */
+ if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
@@ -9764,7 +9784,21 @@ build_binary_op (location_t location, enum tree_code code,
break;
case LSHIFT_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+ if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+ && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
&& code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST)
@@ -9786,9 +9820,10 @@ build_binary_op (location_t location, enum tree_code code,
/* Use the type of the value to be shifted. */
result_type = type0;
- /* Convert the shift-count to an integer, regardless of size
- of value being shifted. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+ /* Convert the non vector shift-count to an integer, regardless
+ of size of value being shifted. */
+ if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
diff --git a/gcc/combine.c b/gcc/combine.c
index 5ec7ee3afce..88b3ca5e15f 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1594,11 +1594,11 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
if (GET_MODE_BITSIZE (GET_MODE (x)) < BITS_PER_WORD
&& CONST_INT_P (src)
&& INTVAL (src) > 0
- && 0 != (INTVAL (src)
- & ((HOST_WIDE_INT) 1
+ && 0 != (UINTVAL (src)
+ & ((unsigned HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
- src = GEN_INT (INTVAL (src)
- | ((HOST_WIDE_INT) (-1)
+ src = GEN_INT (UINTVAL (src)
+ | ((unsigned HOST_WIDE_INT) (-1)
<< GET_MODE_BITSIZE (GET_MODE (x))));
#endif
@@ -2091,7 +2091,7 @@ contains_muldiv (rtx x)
case MULT:
return ! (CONST_INT_P (XEXP (x, 1))
- && exact_log2 (INTVAL (XEXP (x, 1))) >= 0);
+ && exact_log2 (UINTVAL (XEXP (x, 1))) >= 0);
default:
if (BINARY_P (x))
return contains_muldiv (XEXP (x, 0))
@@ -3486,7 +3486,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p)
if (split_code == MULT
&& CONST_INT_P (XEXP (*split, 1))
&& INTVAL (XEXP (*split, 1)) > 0
- && (i = exact_log2 (INTVAL (XEXP (*split, 1)))) >= 0)
+ && (i = exact_log2 (UINTVAL (XEXP (*split, 1)))) >= 0)
{
SUBST (*split, gen_rtx_ASHIFT (split_mode,
XEXP (*split, 0), GEN_INT (i)));
@@ -4576,7 +4576,8 @@ find_split_point (rtx *loc, rtx insn, bool set_src)
unsigned HOST_WIDE_INT src = INTVAL (SET_SRC (x));
rtx dest = XEXP (SET_DEST (x), 0);
enum machine_mode mode = GET_MODE (dest);
- unsigned HOST_WIDE_INT mask = ((HOST_WIDE_INT) 1 << len) - 1;
+ unsigned HOST_WIDE_INT mask
+ = ((unsigned HOST_WIDE_INT) 1 << len) - 1;
rtx or_mask;
if (BITS_BIG_ENDIAN)
@@ -4621,7 +4622,7 @@ find_split_point (rtx *loc, rtx insn, bool set_src)
if (CONST_INT_P (XEXP (SET_SRC (x), 1))
&& REG_P (XEXP (SET_SRC (x), 0))
- && (pos = exact_log2 (INTVAL (XEXP (SET_SRC (x), 1)))) >= 7
+ && (pos = exact_log2 (UINTVAL (XEXP (SET_SRC (x), 1)))) >= 7
&& REG_P (SET_DEST (x))
&& (split = find_single_use (SET_DEST (x), insn, (rtx*) 0)) != 0
&& (GET_CODE (*split) == EQ || GET_CODE (*split) == NE)
@@ -4713,7 +4714,8 @@ find_split_point (rtx *loc, rtx insn, bool set_src)
gen_rtx_LSHIFTRT
(mode, gen_lowpart (mode, inner),
GEN_INT (pos)),
- GEN_INT (((HOST_WIDE_INT) 1 << len) - 1)));
+ GEN_INT (((unsigned HOST_WIDE_INT) 1 << len)
+ - 1)));
split = find_split_point (&SET_SRC (x), insn, true);
if (split && split != &SET_SRC (x))
@@ -5471,7 +5473,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
whose value is a comparison can be replaced with a subreg if
STORE_FLAG_VALUE permits. */
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
- && ((HOST_WIDE_INT) STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0
+ && (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0
&& (temp = get_last_value (XEXP (x, 0)))
&& COMPARISON_P (temp))
return gen_lowpart (mode, XEXP (x, 0));
@@ -5506,13 +5508,13 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
&& CONST_INT_P (XEXP (x, 1))
&& CONST_INT_P (XEXP (XEXP (x, 0), 1))
&& INTVAL (XEXP (x, 1)) == -INTVAL (XEXP (XEXP (x, 0), 1))
- && ((i = exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) >= 0
- || (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0)
+ && ((i = exact_log2 (UINTVAL (XEXP (XEXP (x, 0), 1)))) >= 0
+ || (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0)
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& ((GET_CODE (XEXP (XEXP (x, 0), 0)) == AND
&& CONST_INT_P (XEXP (XEXP (XEXP (x, 0), 0), 1))
- && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))
- == ((HOST_WIDE_INT) 1 << (i + 1)) - 1))
+ && (UINTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))
+ == ((unsigned HOST_WIDE_INT) 1 << (i + 1)) - 1))
|| (GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)))
== (unsigned int) i + 1))))
@@ -5564,7 +5566,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
(and <foo> (const_int pow2-1)) */
if (GET_CODE (XEXP (x, 1)) == AND
&& CONST_INT_P (XEXP (XEXP (x, 1), 1))
- && exact_log2 (-INTVAL (XEXP (XEXP (x, 1), 1))) >= 0
+ && exact_log2 (-UINTVAL (XEXP (XEXP (x, 1), 1))) >= 0
&& rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
return simplify_and_const_int (NULL_RTX, mode, XEXP (x, 0),
-INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
@@ -5598,7 +5600,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
/* If this is a divide by a power of two, treat it as a shift if
its first operand is a shift. */
if (CONST_INT_P (XEXP (x, 1))
- && (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0
+ && (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0
&& (GET_CODE (XEXP (x, 0)) == ASHIFT
|| GET_CODE (XEXP (x, 0)) == LSHIFTRT
|| GET_CODE (XEXP (x, 0)) == ASHIFTRT
@@ -5798,7 +5800,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
else if (SHIFT_COUNT_TRUNCATED && !REG_P (XEXP (x, 1)))
SUBST (XEXP (x, 1),
force_to_mode (XEXP (x, 1), GET_MODE (XEXP (x, 1)),
- ((HOST_WIDE_INT) 1
+ ((unsigned HOST_WIDE_INT) 1
<< exact_log2 (GET_MODE_BITSIZE (GET_MODE (x))))
- 1,
0));
@@ -6129,10 +6131,10 @@ simplify_if_then_else (rtx x)
if (true_code == NE && XEXP (cond, 1) == const0_rtx
&& false_rtx == const0_rtx && CONST_INT_P (true_rtx)
&& ((1 == nonzero_bits (XEXP (cond, 0), mode)
- && (i = exact_log2 (INTVAL (true_rtx))) >= 0)
+ && (i = exact_log2 (UINTVAL (true_rtx))) >= 0)
|| ((num_sign_bit_copies (XEXP (cond, 0), mode)
== GET_MODE_BITSIZE (mode))
- && (i = exact_log2 (-INTVAL (true_rtx))) >= 0)))
+ && (i = exact_log2 (-UINTVAL (true_rtx))) >= 0)))
return
simplify_shift_const (NULL_RTX, ASHIFT, mode,
gen_lowpart (mode, XEXP (cond, 0)), i);
@@ -6141,9 +6143,9 @@ simplify_if_then_else (rtx x)
if (true_code == NE && XEXP (cond, 1) == const0_rtx
&& false_rtx == const0_rtx && CONST_INT_P (true_rtx)
&& GET_MODE (XEXP (cond, 0)) == mode
- && (INTVAL (true_rtx) & GET_MODE_MASK (mode))
+ && (UINTVAL (true_rtx) & GET_MODE_MASK (mode))
== nonzero_bits (XEXP (cond, 0), mode)
- && (i = exact_log2 (INTVAL (true_rtx) & GET_MODE_MASK (mode))) >= 0)
+ && (i = exact_log2 (UINTVAL (true_rtx) & GET_MODE_MASK (mode))) >= 0)
return XEXP (cond, 0);
return x;
@@ -6172,7 +6174,7 @@ simplify_set (rtx x)
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
{
- src = force_to_mode (src, mode, ~(HOST_WIDE_INT) 0, 0);
+ src = force_to_mode (src, mode, ~(unsigned HOST_WIDE_INT) 0, 0);
SUBST (SET_SRC (x), src);
}
@@ -6717,8 +6719,7 @@ expand_compound_operation (rtx x)
&& COMPARISON_P (XEXP (XEXP (x, 0), 0))
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
<= HOST_BITS_PER_WIDE_INT)
- && ((HOST_WIDE_INT) STORE_FLAG_VALUE
- & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+ && (STORE_FLAG_VALUE & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
return XEXP (XEXP (x, 0), 0);
/* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)). */
@@ -6728,8 +6729,7 @@ expand_compound_operation (rtx x)
&& COMPARISON_P (SUBREG_REG (XEXP (x, 0)))
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
<= HOST_BITS_PER_WIDE_INT)
- && ((HOST_WIDE_INT) STORE_FLAG_VALUE
- & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+ && (STORE_FLAG_VALUE & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
return SUBREG_REG (XEXP (x, 0));
}
@@ -6766,7 +6766,7 @@ expand_compound_operation (rtx x)
simplify_shift_const (NULL_RTX, LSHIFTRT,
GET_MODE (x),
XEXP (x, 0), pos),
- ((HOST_WIDE_INT) 1 << len) - 1);
+ ((unsigned HOST_WIDE_INT) 1 << len) - 1);
else
/* Any other cases we can't handle. */
return x;
@@ -6887,7 +6887,7 @@ expand_field_assignment (const_rtx x)
/* Now compute the equivalent expression. Make a copy of INNER
for the SET_DEST in case it is a MEM into which we will substitute;
we don't want shared RTL in that case. */
- mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
+ mask = GEN_INT (((unsigned HOST_WIDE_INT) 1 << len) - 1);
cleared = simplify_gen_binary (AND, compute_mode,
simplify_gen_unary (NOT, compute_mode,
simplify_gen_binary (ASHIFT,
@@ -6963,7 +6963,7 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
else if (GET_CODE (inner) == ASHIFT
&& CONST_INT_P (XEXP (inner, 1))
&& pos_rtx == 0 && pos == 0
- && len > (unsigned HOST_WIDE_INT) INTVAL (XEXP (inner, 1)))
+ && len > UINTVAL (XEXP (inner, 1)))
{
/* We're extracting the least significant bits of an rtx
(ashift X (const_int C)), where LEN > C. Extract the
@@ -7369,7 +7369,8 @@ extract_left_shift (rtx x, int count)
/* If we can safely shift this constant and we find the inner shift,
make a new operation. */
if (CONST_INT_P (XEXP (x, 1))
- && (INTVAL (XEXP (x, 1)) & ((((HOST_WIDE_INT) 1 << count)) - 1)) == 0
+ && (UINTVAL (XEXP (x, 1))
+ & ((((unsigned HOST_WIDE_INT) 1 << count)) - 1)) == 0
&& (tem = extract_left_shift (XEXP (x, 0), count)) != 0)
return simplify_gen_binary (code, mode, tem,
GEN_INT (INTVAL (XEXP (x, 1)) >> count));
@@ -7519,7 +7520,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
/* If the constant is a power of two minus one and the first operand
is a logical right shift, make an extraction. */
if (GET_CODE (XEXP (x, 0)) == LSHIFTRT
- && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
+ && (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
{
new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
new_rtx = make_extraction (mode, new_rtx, 0, XEXP (XEXP (x, 0), 1), i, 1,
@@ -7530,7 +7531,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
else if (GET_CODE (XEXP (x, 0)) == SUBREG
&& subreg_lowpart_p (XEXP (x, 0))
&& GET_CODE (SUBREG_REG (XEXP (x, 0))) == LSHIFTRT
- && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
+ && (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
{
new_rtx = make_compound_operation (XEXP (SUBREG_REG (XEXP (x, 0)), 0),
next_code);
@@ -7543,7 +7544,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
|| GET_CODE (XEXP (x, 0)) == IOR)
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == LSHIFTRT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == LSHIFTRT
- && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
+ && (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
{
/* Apply the distributive law, and then try to make extractions. */
new_rtx = gen_rtx_fmt_ee (GET_CODE (XEXP (x, 0)), mode,
@@ -7559,7 +7560,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
else if (GET_CODE (XEXP (x, 0)) == ROTATE
&& CONST_INT_P (XEXP (XEXP (x, 0), 1))
- && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0
+ && (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0
&& i <= INTVAL (XEXP (XEXP (x, 0), 1)))
{
new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
@@ -7595,7 +7596,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
representable by an extraction even if no shift is present.
If it doesn't end up being a ZERO_EXTEND, we will ignore it unless
we are in a COMPARE. */
- else if ((i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
+ else if ((i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
new_rtx = make_extraction (mode,
make_compound_operation (XEXP (x, 0),
next_code),
@@ -7604,7 +7605,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
/* If we are in a comparison and this is an AND with a power of two,
convert this into the appropriate bit extract. */
else if (in_code == COMPARE
- && (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0)
+ && (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0)
new_rtx = make_extraction (mode,
make_compound_operation (XEXP (x, 0),
next_code),
@@ -7685,7 +7686,8 @@ make_compound_operation (rtx x, enum rtx_code in_code)
&& GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
&& subreg_lowpart_p (x))
{
- rtx newer = force_to_mode (tem, mode, ~(HOST_WIDE_INT) 0, 0);
+ rtx newer
+ = force_to_mode (tem, mode, ~(unsigned HOST_WIDE_INT) 0, 0);
/* If we have something other than a SUBREG, we might have
done an expansion, so rerun ourselves. */
@@ -8047,16 +8049,17 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
&& GET_MODE_MASK (GET_MODE (x)) != mask
&& GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
{
- HOST_WIDE_INT cval = (INTVAL (XEXP (x, 1))
- | (GET_MODE_MASK (GET_MODE (x)) & ~mask));
+ unsigned HOST_WIDE_INT cval
+ = UINTVAL (XEXP (x, 1))
+ | (GET_MODE_MASK (GET_MODE (x)) & ~mask);
int width = GET_MODE_BITSIZE (GET_MODE (x));
rtx y;
/* If MODE is narrower than HOST_WIDE_INT and CVAL is a negative
number, sign extend it. */
if (width > 0 && width < HOST_BITS_PER_WIDE_INT
- && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
- cval |= (HOST_WIDE_INT) -1 << width;
+ && (cval & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
+ cval |= (unsigned HOST_WIDE_INT) -1 << width;
y = simplify_gen_binary (AND, GET_MODE (x),
XEXP (x, 0), GEN_INT (cval));
@@ -8084,8 +8087,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
number, sign extend it. */
if (width < HOST_BITS_PER_WIDE_INT
- && (smask & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
- smask |= (HOST_WIDE_INT) -1 << width;
+ && (smask & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
+ smask |= (unsigned HOST_WIDE_INT) (-1) << width;
if (CONST_INT_P (XEXP (x, 1))
&& exact_log2 (- smask) >= 0
@@ -8121,8 +8124,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
/* Similarly, if C contains every bit in the fuller_mask, then we may
replace with (not Y). */
if (CONST_INT_P (XEXP (x, 0))
- && ((INTVAL (XEXP (x, 0)) | (HOST_WIDE_INT) fuller_mask)
- == INTVAL (XEXP (x, 0))))
+ && ((UINTVAL (XEXP (x, 0)) | fuller_mask) == UINTVAL (XEXP (x, 0))))
{
x = simplify_gen_unary (NOT, GET_MODE (x),
XEXP (x, 1), GET_MODE (x));
@@ -8147,7 +8149,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
&& ((INTVAL (XEXP (XEXP (x, 0), 1))
+ floor_log2 (INTVAL (XEXP (x, 1))))
< GET_MODE_BITSIZE (GET_MODE (x)))
- && (INTVAL (XEXP (x, 1))
+ && (UINTVAL (XEXP (x, 1))
& ~nonzero_bits (XEXP (x, 0), GET_MODE (x))) == 0)
{
temp = GEN_INT ((INTVAL (XEXP (x, 1)) & mask)
@@ -8294,7 +8296,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
if (GET_MODE_BITSIZE (GET_MODE (x)) > HOST_BITS_PER_WIDE_INT)
{
- nonzero = ~(HOST_WIDE_INT) 0;
+ nonzero = ~(unsigned HOST_WIDE_INT) 0;
/* GET_MODE_BITSIZE (GET_MODE (x)) - INTVAL (XEXP (x, 1))
is the number of bits a full-width mask would have set.
@@ -8425,7 +8427,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
/* (and (ne FOO 0) CONST) can be (and FOO CONST) if CONST is included
in STORE_FLAG_VALUE and FOO has a single bit that might be nonzero,
which is equal to STORE_FLAG_VALUE. */
- if ((mask & ~STORE_FLAG_VALUE) == 0 && XEXP (x, 1) == const0_rtx
+ if ((mask & ~STORE_FLAG_VALUE) == 0
+ && XEXP (x, 1) == const0_rtx
&& GET_MODE (XEXP (x, 0)) == mode
&& exact_log2 (nonzero_bits (XEXP (x, 0), mode)) >= 0
&& (nonzero_bits (XEXP (x, 0), mode)
@@ -9014,8 +9017,8 @@ make_field_assignment (rtx x)
&& INTVAL (XEXP (assign, 1)) < HOST_BITS_PER_WIDE_INT
&& GET_CODE (src) == AND
&& CONST_INT_P (XEXP (src, 1))
- && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (src, 1))
- == ((unsigned HOST_WIDE_INT) 1 << INTVAL (XEXP (assign, 1))) - 1))
+ && UINTVAL (XEXP (src, 1))
+ == ((unsigned HOST_WIDE_INT) 1 << INTVAL (XEXP (assign, 1))) - 1)
src = XEXP (src, 0);
return gen_rtx_SET (VOIDmode, assign, src);
@@ -9417,11 +9420,11 @@ reg_nonzero_bits_for_combine (const_rtx x, enum machine_mode mode,
if (GET_MODE_BITSIZE (GET_MODE (x)) < GET_MODE_BITSIZE (mode)
&& CONST_INT_P (tem)
&& INTVAL (tem) > 0
- && 0 != (INTVAL (tem)
- & ((HOST_WIDE_INT) 1
+ && 0 != (UINTVAL (tem)
+ & ((unsigned HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
- tem = GEN_INT (INTVAL (tem)
- | ((HOST_WIDE_INT) (-1)
+ tem = GEN_INT (UINTVAL (tem)
+ | ((unsigned HOST_WIDE_INT) (-1)
<< GET_MODE_BITSIZE (GET_MODE (x))));
#endif
return tem;
@@ -9815,8 +9818,8 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
if (GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
&& code == ASHIFTRT
&& ((nonzero_bits (varop, shift_mode)
- & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (shift_mode) - 1)))
- == 0))
+ & ((unsigned HOST_WIDE_INT) 1
+ << (GET_MODE_BITSIZE (shift_mode) - 1))) == 0))
code = LSHIFTRT;
if (((code == LSHIFTRT
@@ -9889,13 +9892,13 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
is cheaper. But it is still better on those machines to
merge two shifts into one. */
if (CONST_INT_P (XEXP (varop, 1))
- && exact_log2 (INTVAL (XEXP (varop, 1))) >= 0)
+ && exact_log2 (UINTVAL (XEXP (varop, 1))) >= 0)
{
varop
= simplify_gen_binary (ASHIFT, GET_MODE (varop),
XEXP (varop, 0),
GEN_INT (exact_log2 (
- INTVAL (XEXP (varop, 1)))));
+ UINTVAL (XEXP (varop, 1)))));
continue;
}
break;
@@ -9903,13 +9906,13 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
case UDIV:
/* Similar, for when divides are cheaper. */
if (CONST_INT_P (XEXP (varop, 1))
- && exact_log2 (INTVAL (XEXP (varop, 1))) >= 0)
+ && exact_log2 (UINTVAL (XEXP (varop, 1))) >= 0)
{
varop
= simplify_gen_binary (LSHIFTRT, GET_MODE (varop),
XEXP (varop, 0),
GEN_INT (exact_log2 (
- INTVAL (XEXP (varop, 1)))));
+ UINTVAL (XEXP (varop, 1)))));
continue;
}
break;
@@ -9961,8 +9964,8 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
{
/* C3 has the low-order C1 bits zero. */
- mask = (GET_MODE_MASK (mode)
- & ~(((HOST_WIDE_INT) 1 << first_count) - 1));
+ mask = GET_MODE_MASK (mode)
+ & ~(((unsigned HOST_WIDE_INT) 1 << first_count) - 1);
varop = simplify_and_const_int (NULL_RTX, result_mode,
XEXP (varop, 0), mask);
@@ -10184,8 +10187,7 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
&& GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT
&& STORE_FLAG_VALUE == -1
&& nonzero_bits (XEXP (varop, 0), result_mode) == 1
- && merge_outer_ops (&outer_op, &outer_const, XOR,
- (HOST_WIDE_INT) 1, result_mode,
+ && merge_outer_ops (&outer_op, &outer_const, XOR, 1, result_mode,
&complement_p))
{
varop = XEXP (varop, 0);
@@ -10209,8 +10211,7 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
/* NEG commutes with ASHIFT since it is multiplication. Move the
NEG outside to allow shifts to combine. */
if (code == ASHIFT
- && merge_outer_ops (&outer_op, &outer_const, NEG,
- (HOST_WIDE_INT) 0, result_mode,
+ && merge_outer_ops (&outer_op, &outer_const, NEG, 0, result_mode,
&complement_p))
{
varop = XEXP (varop, 0);
@@ -10226,8 +10227,7 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
&& count == (GET_MODE_BITSIZE (result_mode) - 1)
&& XEXP (varop, 1) == constm1_rtx
&& nonzero_bits (XEXP (varop, 0), result_mode) == 1
- && merge_outer_ops (&outer_op, &outer_const, XOR,
- (HOST_WIDE_INT) 1, result_mode,
+ && merge_outer_ops (&outer_op, &outer_const, XOR, 1, result_mode,
&complement_p))
{
count = 0;
@@ -10951,7 +10951,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
else if (const_op == 0
&& mode_width <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (op0, mode)
- & ((HOST_WIDE_INT) 1 << (mode_width - 1))) == 0)
+ & ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)))
+ == 0)
code = EQ;
break;
@@ -10981,7 +10982,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
else if (const_op == 0
&& mode_width <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (op0, mode)
- & ((HOST_WIDE_INT) 1 << (mode_width - 1))) == 0)
+ & ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)))
+ == 0)
code = NE;
break;
@@ -10996,8 +10998,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
}
/* (unsigned) < 0x80000000 is equivalent to >= 0. */
- else if ((mode_width <= HOST_BITS_PER_WIDE_INT)
- && (const_op == (HOST_WIDE_INT) 1 << (mode_width - 1)))
+ else if (mode_width <= HOST_BITS_PER_WIDE_INT
+ && (unsigned HOST_WIDE_INT) const_op
+ == (unsigned HOST_WIDE_INT) 1 << (mode_width - 1))
{
const_op = 0, op1 = const0_rtx;
code = GE;
@@ -11012,8 +11015,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
code = EQ;
/* (unsigned) <= 0x7fffffff is equivalent to >= 0. */
- else if ((mode_width <= HOST_BITS_PER_WIDE_INT)
- && (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1))
+ else if (mode_width <= HOST_BITS_PER_WIDE_INT
+ && (unsigned HOST_WIDE_INT) const_op
+ == ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)) - 1)
{
const_op = 0, op1 = const0_rtx;
code = GE;
@@ -11031,8 +11035,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
}
/* (unsigned) >= 0x80000000 is equivalent to < 0. */
- else if ((mode_width <= HOST_BITS_PER_WIDE_INT)
- && (const_op == (HOST_WIDE_INT) 1 << (mode_width - 1)))
+ else if (mode_width <= HOST_BITS_PER_WIDE_INT
+ && (unsigned HOST_WIDE_INT) const_op
+ == (unsigned HOST_WIDE_INT) 1 << (mode_width - 1))
{
const_op = 0, op1 = const0_rtx;
code = LT;
@@ -11047,8 +11052,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
code = NE;
/* (unsigned) > 0x7fffffff is equivalent to < 0. */
- else if ((mode_width <= HOST_BITS_PER_WIDE_INT)
- && (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1))
+ else if (mode_width <= HOST_BITS_PER_WIDE_INT
+ && (unsigned HOST_WIDE_INT) const_op
+ == ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)) - 1)
{
const_op = 0, op1 = const0_rtx;
code = LT;
@@ -11071,8 +11077,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
if (sign_bit_comparison_p
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
op0 = force_to_mode (op0, mode,
- ((HOST_WIDE_INT) 1
- << (GET_MODE_BITSIZE (mode) - 1)),
+ (unsigned HOST_WIDE_INT) 1
+ << (GET_MODE_BITSIZE (mode) - 1),
0);
/* Now try cases based on the opcode of OP0. If none of the cases
@@ -11092,7 +11098,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& CONST_INT_P (XEXP (op0, 0))
&& XEXP (op0, 1) == const1_rtx
&& equality_comparison_p && const_op == 0
- && (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0)
+ && (i = exact_log2 (UINTVAL (XEXP (op0, 0)))) >= 0)
{
if (BITS_BIG_ENDIAN)
{
@@ -11168,7 +11174,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& (GET_CODE (XEXP (op0, 0)) == ABS
|| (mode_width <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (XEXP (op0, 0), mode)
- & ((HOST_WIDE_INT) 1 << (mode_width - 1))) == 0)))
+ & ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)))
+ == 0)))
{
op0 = XEXP (op0, 0);
code = (code == LT ? NE : EQ);
@@ -11205,7 +11212,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& mode_width <= HOST_BITS_PER_WIDE_INT)
{
op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0),
- ((HOST_WIDE_INT) 1
+ ((unsigned HOST_WIDE_INT) 1
<< (mode_width - 1
- INTVAL (XEXP (op0, 1)))));
code = (code == LT ? NE : EQ);
@@ -11382,8 +11389,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
of bits in X minus 1, is one iff X > 0. */
if (sign_bit_comparison_p && GET_CODE (XEXP (op0, 0)) == ASHIFTRT
&& CONST_INT_P (XEXP (XEXP (op0, 0), 1))
- && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (op0, 0), 1))
- == mode_width - 1
+ && UINTVAL (XEXP (XEXP (op0, 0), 1)) == mode_width - 1
&& rtx_equal_p (XEXP (XEXP (op0, 0), 0), XEXP (op0, 1)))
{
op0 = XEXP (op0, 1);
@@ -11429,7 +11435,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
|| (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
&& (STORE_FLAG_VALUE
- & (((HOST_WIDE_INT) 1
+ & (((unsigned HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
&& (code == LT || code == GE)))
{
@@ -11469,11 +11475,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& GET_CODE (XEXP (op0, 0)) == ASHIFT
&& XEXP (XEXP (op0, 0), 0) == const1_rtx)
{
- op0 = simplify_and_const_int
- (NULL_RTX, mode, gen_rtx_LSHIFTRT (mode,
- XEXP (op0, 1),
- XEXP (XEXP (op0, 0), 1)),
- (HOST_WIDE_INT) 1);
+ op0 = gen_rtx_LSHIFTRT (mode, XEXP (op0, 1),
+ XEXP (XEXP (op0, 0), 1));
+ op0 = simplify_and_const_int (NULL_RTX, mode, op0, 1);
continue;
}
@@ -11530,7 +11534,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
transformation is invalid. */
if ((equality_comparison_p || unsigned_comparison_p)
&& CONST_INT_P (XEXP (op0, 1))
- && (i = exact_log2 ((INTVAL (XEXP (op0, 1))
+ && (i = exact_log2 ((UINTVAL (XEXP (op0, 1))
& GET_MODE_MASK (mode))
+ 1)) >= 0
&& const_op >> i == 0
@@ -11590,8 +11594,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& XEXP (op0, 1) == const1_rtx
&& GET_CODE (XEXP (op0, 0)) == NOT)
{
- op0 = simplify_and_const_int
- (NULL_RTX, mode, XEXP (XEXP (op0, 0), 0), (HOST_WIDE_INT) 1);
+ op0 = simplify_and_const_int (NULL_RTX, mode,
+ XEXP (XEXP (op0, 0), 0), 1);
code = (code == NE ? EQ : NE);
continue;
}
@@ -11611,13 +11615,13 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& CONST_INT_P (XEXP (shift_op, 1))
&& CONST_INT_P (shift_count)
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
- && (INTVAL (XEXP (shift_op, 1))
- == (HOST_WIDE_INT) 1 << INTVAL (shift_count))))
+ && (UINTVAL (XEXP (shift_op, 1))
+ == (unsigned HOST_WIDE_INT) 1
+ << INTVAL (shift_count))))
{
- op0 = simplify_and_const_int
- (NULL_RTX, mode,
- gen_rtx_LSHIFTRT (mode, XEXP (shift_op, 0), shift_count),
- (HOST_WIDE_INT) 1);
+ op0
+ = gen_rtx_LSHIFTRT (mode, XEXP (shift_op, 0), shift_count);
+ op0 = simplify_and_const_int (NULL_RTX, mode, op0, 1);
code = (code == NE ? EQ : NE);
continue;
}
@@ -11634,8 +11638,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& INTVAL (XEXP (op0, 1)) >= 0
&& ((INTVAL (XEXP (op0, 1)) + ! equality_comparison_p)
< HOST_BITS_PER_WIDE_INT)
- && ((const_op
- & (((HOST_WIDE_INT) 1 << INTVAL (XEXP (op0, 1))) - 1)) == 0)
+ && (((unsigned HOST_WIDE_INT) const_op
+ & (((unsigned HOST_WIDE_INT) 1 << INTVAL (XEXP (op0, 1)))
+ - 1)) == 0)
&& mode_width <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (XEXP (op0, 0), mode)
& ~(mask >> (INTVAL (XEXP (op0, 1))
@@ -11657,7 +11662,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& mode_width <= HOST_BITS_PER_WIDE_INT)
{
op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0),
- ((HOST_WIDE_INT) 1
+ ((unsigned HOST_WIDE_INT) 1
<< (mode_width - 1
- INTVAL (XEXP (op0, 1)))));
code = (code == LT ? NE : EQ);
@@ -11669,11 +11674,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
low-order bit. */
if (const_op == 0 && equality_comparison_p
&& CONST_INT_P (XEXP (op0, 1))
- && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
- == mode_width - 1)
+ && UINTVAL (XEXP (op0, 1)) == mode_width - 1)
{
- op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0),
- (HOST_WIDE_INT) 1);
+ op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0), 1);
continue;
}
break;
@@ -11780,8 +11783,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
if (const_op == 0
&& (equality_comparison_p || sign_bit_comparison_p)
&& CONST_INT_P (XEXP (op0, 1))
- && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
- == mode_width - 1)
+ && UINTVAL (XEXP (op0, 1)) == mode_width - 1)
{
op0 = XEXP (op0, 0);
code = (code == NE || code == GT ? LT : GE);
@@ -11878,7 +11880,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
{
op0 = simplify_gen_binary (AND, tmode,
gen_lowpart (tmode, op0),
- GEN_INT ((HOST_WIDE_INT) 1
+ GEN_INT ((unsigned HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (mode)
- 1)));
code = (code == LT) ? NE : EQ;
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 5031b99e2f7..b12c8daf951 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -94,6 +94,10 @@ static void arc_external_libcall (rtx);
static bool arc_return_in_memory (const_tree, const_tree);
static bool arc_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
const_tree, bool);
+static rtx arc_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
+static void arc_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
static void arc_trampoline_init (rtx, tree, rtx);
static void arc_option_override (void);
@@ -148,6 +152,10 @@ static const struct attribute_spec arc_attribute_table[] =
#define TARGET_RETURN_IN_MEMORY arc_return_in_memory
#undef TARGET_PASS_BY_REFERENCE
#define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG arc_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
#undef TARGET_CALLEE_COPIES
#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
@@ -2354,6 +2362,67 @@ arc_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
return size > 8;
}
+/* Round SIZE up to a word boundary. */
+#define ROUND_ADVANCE(SIZE) \
+(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Round arg MODE/TYPE up to the next word boundary. */
+#define ROUND_ADVANCE_ARG(MODE, TYPE) \
+((MODE) == BLKmode \
+ ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \
+ : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))
+
+/* Round CUM up to the necessary point for argument MODE/TYPE. */
+#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \
+((((MODE) == BLKmode ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) \
+ > BITS_PER_WORD) \
+ ? (((CUM) + 1) & ~1) \
+ : (CUM))
+
+/* Return boolean indicating arg of type TYPE and mode MODE will be passed in
+ a reg. This includes arguments that have to be passed by reference as the
+ pointer to them is passed in a reg if one is available (and that is what
+ we're given). */
+#define PASS_IN_REG_P(CUM, MODE, TYPE) \
+((CUM) < MAX_ARC_PARM_REGS \
+ && ((ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \
+ + ROUND_ADVANCE_ARG ((MODE), (TYPE)) \
+ <= MAX_ARC_PARM_REGS)))
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
+ and the rest are pushed. */
+
+static rtx
+arc_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ return (PASS_IN_REG_P (*cum, mode, type)
+ ? gen_rtx_REG (mode, ROUND_ADVANCE_CUM (*cum, mode, type))
+ : NULL_RTX);
+}
+
+/* Worker function for TARGET_FUNCTION_ARG_ADVANCE. */
+
+static void
+arc_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ *cum = (ROUND_ADVANCE_CUM (*cum, mode, type)
+ + ROUND_ADVANCE_ARG (mode, type));
+}
+
/* Trampolines. */
/* ??? This doesn't work yet because GCC will use as the address of a nested
function the address of the trampoline. We need to use that address
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 93f5a7feccf..078914adf6f 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -520,61 +520,6 @@ extern enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
#define FUNCTION_ARG_REGNO_P(N) \
((unsigned) (N) < MAX_ARC_PARM_REGS)
-/* The ROUND_ADVANCE* macros are local to this file. */
-/* Round SIZE up to a word boundary. */
-#define ROUND_ADVANCE(SIZE) \
-(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Round arg MODE/TYPE up to the next word boundary. */
-#define ROUND_ADVANCE_ARG(MODE, TYPE) \
-((MODE) == BLKmode \
- ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \
- : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))
-
-/* Round CUM up to the necessary point for argument MODE/TYPE. */
-#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \
-((((MODE) == BLKmode ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) \
- > BITS_PER_WORD) \
- ? (((CUM) + 1) & ~1) \
- : (CUM))
-
-/* Return boolean indicating arg of type TYPE and mode MODE will be passed in
- a reg. This includes arguments that have to be passed by reference as the
- pointer to them is passed in a reg if one is available (and that is what
- we're given).
- This macro is only used in this file. */
-#define PASS_IN_REG_P(CUM, MODE, TYPE) \
-((CUM) < MAX_ARC_PARM_REGS \
- && ((ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \
- + ROUND_ADVANCE_ARG ((MODE), (TYPE)) \
- <= MAX_ARC_PARM_REGS)))
-
-/* Determine where to put an argument to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
- and the rest are pushed. */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-(PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \
- ? gen_rtx_REG ((MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \
- : 0)
-
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
-((CUM) = (ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \
- + ROUND_ADVANCE_ARG ((MODE), (TYPE))))
-
/* If defined, a C expression that gives the alignment boundary, in bits,
of an argument with the specified mode and type. If it is not defined,
PARM_BOUNDARY is used for all arguments. */
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 2586a272857..a246d5b64d9 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -2363,11 +2363,17 @@ const_ok_for_arm (HOST_WIDE_INT i)
{
HOST_WIDE_INT v;
- /* Allow repeated pattern. */
+ /* Allow repeated patterns 0x00XY00XY or 0xXYXYXYXY. */
v = i & 0xff;
v |= v << 16;
if (i == v || i == (v | (v << 8)))
return TRUE;
+
+ /* Allow repeated pattern 0xXY00XY00. */
+ v = i & 0xff00;
+ v |= v << 16;
+ if (i == v)
+ return TRUE;
}
return FALSE;
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 11e307138e4..fd5e0958ac5 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -129,6 +129,12 @@ static bool cris_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
const_tree, bool);
static int cris_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
+static rtx cris_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
+static rtx cris_function_incoming_arg (CUMULATIVE_ARGS *,
+ enum machine_mode, const_tree, bool);
+static void cris_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
static tree cris_md_asm_clobbers (tree, tree, tree);
static bool cris_handle_option (size_t, const char *, int);
@@ -214,6 +220,12 @@ static const struct default_options cris_option_optimization_table[] =
#define TARGET_PASS_BY_REFERENCE cris_pass_by_reference
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES cris_arg_partial_bytes
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG cris_function_arg
+#undef TARGET_FUNCTION_INCOMING_ARG
+#define TARGET_FUNCTION_INCOMING_ARG cris_function_incoming_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE cris_function_arg_advance
#undef TARGET_MD_ASM_CLOBBERS
#define TARGET_MD_ASM_CLOBBERS cris_md_asm_clobbers
#undef TARGET_DEFAULT_TARGET_FLAGS
@@ -3891,6 +3903,51 @@ cris_arg_partial_bytes (CUMULATIVE_ARGS *ca, enum machine_mode mode,
return 0;
}
+static rtx
+cris_function_arg_1 (const CUMULATIVE_ARGS *ca,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named, bool incoming)
+{
+ if ((!incoming || named) && ca->regs < CRIS_MAX_ARGS_IN_REGS)
+ return gen_rtx_REG (mode, CRIS_FIRST_ARG_REG + ca->regs);
+ else
+ return NULL_RTX;
+}
+
+/* Worker function for TARGET_FUNCTION_ARG.
+ The void_type_node is sent as a "closing" call. */
+
+static rtx
+cris_function_arg (CUMULATIVE_ARGS *ca, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ return cris_function_arg_1 (ca, mode, type, named, false);
+}
+
+/* Worker function for TARGET_FUNCTION_INCOMING_ARG.
+
+ The differences between this and the previous, is that this one checks
+ that an argument is named, since incoming stdarg/varargs arguments are
+ pushed onto the stack, and we don't have to check against the "closing"
+ void_type_node TYPE parameter. */
+
+static rtx
+cris_function_incoming_arg (CUMULATIVE_ARGS *ca, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ return cris_function_arg_1 (ca, mode, type, named, true);
+}
+
+/* Worker function for TARGET_FUNCTION_ARG_ADVANCE. */
+
+static void
+cris_function_arg_advance (CUMULATIVE_ARGS *ca, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ ca->regs += (3 + CRIS_FUNCTION_ARG_SIZE (mode, type)) / 4;
+}
+
/* Worker function for TARGET_MD_ASM_CLOBBERS. */
static tree
diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h
index 090bcd12084..776c44e2c81 100644
--- a/gcc/config/cris/cris.h
+++ b/gcc/config/cris/cris.h
@@ -848,21 +848,6 @@ enum reg_class
/* Node: Register Arguments */
-/* The void_type_node is sent as a "closing" call. */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ((CUM).regs < CRIS_MAX_ARGS_IN_REGS \
- ? gen_rtx_REG (MODE, (CRIS_FIRST_ARG_REG) + (CUM).regs) \
- : NULL_RTX)
-
-/* The differences between this and the previous, is that this one checks
- that an argument is named, since incoming stdarg/varargs arguments are
- pushed onto the stack, and we don't have to check against the "closing"
- void_type_node TYPE parameter. */
-#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
- ((NAMED) && (CUM).regs < CRIS_MAX_ARGS_IN_REGS \
- ? gen_rtx_REG (MODE, CRIS_FIRST_ARG_REG + (CUM).regs) \
- : NULL_RTX)
-
/* Contrary to what you'd believe, defining FUNCTION_ARG_CALLEE_COPIES
seems like a (small total) loss, at least for gcc-2.7.2 compiling and
running gcc-2.1 (small win in size, small loss running -- 100.1%),
@@ -880,9 +865,6 @@ struct cum_args {int regs;};
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
((CUM).regs = 0)
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- ((CUM).regs += (3 + CRIS_FUNCTION_ARG_SIZE (MODE, TYPE)) / 4)
-
#define FUNCTION_ARG_REGNO_P(REGNO) \
((REGNO) >= CRIS_FIRST_ARG_REG \
&& (REGNO) < CRIS_FIRST_ARG_REG + (CRIS_MAX_ARGS_IN_REGS))
diff --git a/gcc/config/crx/crx-protos.h b/gcc/config/crx/crx-protos.h
index b35051d99f5..208616d4014 100644
--- a/gcc/config/crx/crx-protos.h
+++ b/gcc/config/crx/crx-protos.h
@@ -32,10 +32,8 @@ extern enum reg_class crx_secondary_reload_class (enum reg_class, enum machine_m
/* Passing function arguments. */
extern int crx_function_arg_regno_p (int);
#ifdef TREE_CODE
-extern void crx_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
#ifdef RTX_CODE
extern void crx_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
-extern rtx crx_function_arg (struct cumulative_args *, enum machine_mode, tree, int);
#endif /* RTX_CODE */
#endif /* TREE_CODE */
diff --git a/gcc/config/crx/crx.c b/gcc/config/crx/crx.c
index 3dd642d9025..5fc963a6ce0 100644
--- a/gcc/config/crx/crx.c
+++ b/gcc/config/crx/crx.c
@@ -130,6 +130,10 @@ static bool crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_U
static int crx_address_cost (rtx, bool);
static bool crx_legitimate_address_p (enum machine_mode, rtx, bool);
static bool crx_can_eliminate (const int, const int);
+static rtx crx_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
+static void crx_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
/*****************************************************************************/
/* RTL VALIDITY */
@@ -155,6 +159,16 @@ static bool crx_can_eliminate (const int, const int);
#define TARGET_RETURN_IN_MEMORY crx_return_in_memory
/*****************************************************************************/
+/* PASSING FUNCTION ARGUMENTS */
+/*****************************************************************************/
+
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG crx_function_arg
+
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE crx_function_arg_advance
+
+/*****************************************************************************/
/* RELATIVE COSTS OF OPERATIONS */
/*****************************************************************************/
@@ -429,7 +443,7 @@ crx_hard_regno_mode_ok (int regno, enum machine_mode mode)
* the number of registers needed else 0. */
static int
-enough_regs_for_param (CUMULATIVE_ARGS * cum, tree type,
+enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
enum machine_mode mode)
{
int type_size;
@@ -452,11 +466,11 @@ enough_regs_for_param (CUMULATIVE_ARGS * cum, tree type,
return 0;
}
-/* Implements the macro FUNCTION_ARG defined in crx.h. */
+/* Implements TARGET_FUNCTION_ARG. */
-rtx
-crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type,
- int named ATTRIBUTE_UNUSED)
+static rtx
+crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
{
last_parm_in_reg = 0;
@@ -520,11 +534,11 @@ crx_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
}
}
-/* Implements the macro FUNCTION_ARG_ADVANCE defined in crx.h. */
+/* Implements TARGET_FUNCTION_ARG_ADVANCE. */
-void
+static void
crx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
- tree type, int named ATTRIBUTE_UNUSED)
+ const_tree type, bool named ATTRIBUTE_UNUSED)
{
/* l holds the number of registers required */
int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
diff --git a/gcc/config/crx/crx.h b/gcc/config/crx/crx.h
index 6982eb2cdc4..eac1594c036 100644
--- a/gcc/config/crx/crx.h
+++ b/gcc/config/crx/crx.h
@@ -300,9 +300,6 @@ enum reg_class
#define PUSH_ROUNDING(BYTES) (((BYTES) + 3) & ~3)
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ((rtx) crx_function_arg(&(CUM), (MODE), (TYPE), (NAMED)))
-
#ifndef CUMULATIVE_ARGS
struct cumulative_args
{
@@ -318,9 +315,6 @@ struct cumulative_args
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
crx_init_cumulative_args(&(CUM), (FNTYPE), (LIBNAME))
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- crx_function_arg_advance(&(CUM), (MODE), (TYPE), (NAMED))
-
#define FUNCTION_ARG_REGNO_P(REGNO) crx_function_arg_regno_p(REGNO)
/*****************************************************************************/
diff --git a/gcc/config/fr30/fr30-protos.h b/gcc/config/fr30/fr30-protos.h
index 0ea28a3c798..37fc2a2d2c5 100644
--- a/gcc/config/fr30/fr30-protos.h
+++ b/gcc/config/fr30/fr30-protos.h
@@ -26,9 +26,6 @@ extern int fr30_check_multiple_regs (rtx *, int, int);
extern void fr30_print_operand (FILE *, rtx, int);
extern void fr30_print_operand_address (FILE *, rtx);
extern rtx fr30_move_double (rtx *);
-#ifdef TREE_CODE
-extern int fr30_num_arg_regs (enum machine_mode, tree);
-#endif /* TREE_CODE */
#ifdef HAVE_MACHINE_MODES
#define Mmode enum machine_mode
extern int fr30_const_double_is_zero (rtx);
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index 04e90f23fc2..95bbd61d260 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -119,10 +119,15 @@ static void fr30_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
static bool fr30_must_pass_in_stack (enum machine_mode, const_tree);
static int fr30_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
+static rtx fr30_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
+static void fr30_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
static bool fr30_frame_pointer_required (void);
static bool fr30_can_eliminate (const int, const int);
static void fr30_asm_trampoline_template (FILE *);
static void fr30_trampoline_init (rtx, tree, rtx);
+static int fr30_num_arg_regs (enum machine_mode, const_tree);
#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
#define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
@@ -162,6 +167,10 @@ static const struct default_options fr30_option_optimization_table[] =
#define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES fr30_arg_partial_bytes
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG fr30_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE fr30_function_arg_advance
#undef TARGET_SETUP_INCOMING_VARARGS
#define TARGET_SETUP_INCOMING_VARARGS fr30_setup_incoming_varargs
@@ -711,8 +720,8 @@ fr30_must_pass_in_stack (enum machine_mode mode, const_tree type)
/* Compute the number of word sized registers needed to hold a
function argument of mode INT_MODE and tree type TYPE. */
-int
-fr30_num_arg_regs (enum machine_mode mode, tree type)
+static int
+fr30_num_arg_regs (enum machine_mode mode, const_tree type)
{
int size;
@@ -756,6 +765,33 @@ fr30_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;
}
+static rtx
+fr30_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ if (!named
+ || fr30_must_pass_in_stack (mode, type)
+ || *cum >= FR30_NUM_ARG_REGS)
+ return NULL_RTX;
+ else
+ return gen_rtx_REG (mode, *cum + FIRST_ARG_REGNUM);
+}
+
+/* A C statement (sans semicolon) to update the summarizer variable CUM to
+ advance past an argument in the argument list. The values MODE, TYPE and
+ NAMED describe that argument. Once this is done, the variable CUM is
+ suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
+
+ This macro need not do anything if the argument in question was passed on
+ the stack. The compiler knows how to track the amount of stack space used
+ for arguments without any special help. */
+static void
+fr30_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ *cum += named * fr30_num_arg_regs (mode, type);
+}
+
/*}}}*/
/*{{{ Operand predicates */
diff --git a/gcc/config/fr30/fr30.h b/gcc/config/fr30/fr30.h
index c5c405c159f..0ea72fd8c7c 100644
--- a/gcc/config/fr30/fr30.h
+++ b/gcc/config/fr30/fr30.h
@@ -555,12 +555,6 @@ enum reg_class
#define FR30_NUM_ARG_REGS 4
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ( (NAMED) == 0 ? NULL_RTX \
- : targetm.calls.must_pass_in_stack (MODE, TYPE) ? NULL_RTX \
- : (CUM) >= FR30_NUM_ARG_REGS ? NULL_RTX \
- : gen_rtx_REG (MODE, CUM + FIRST_ARG_REGNUM))
-
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the type
`int' suffices and can hold the number of bytes of argument so far.
@@ -594,17 +588,6 @@ enum reg_class
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
(CUM) = 0
-/* A C statement (sans semicolon) to update the summarizer variable CUM to
- advance past an argument in the argument list. The values MODE, TYPE and
- NAMED describe that argument. Once this is done, the variable CUM is
- suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
-
- This macro need not do anything if the argument in question was passed on
- the stack. The compiler knows how to track the amount of stack space used
- for arguments without any special help. */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (CUM) += (NAMED) * fr30_num_arg_regs (MODE, TYPE)
-
/* A C expression that is nonzero if REGNO is the number of a hard register in
which function arguments are sometimes passed. This does *not* include
implicit arguments such as the static chain and the structure-value address.
diff --git a/gcc/config/frv/frv-protos.h b/gcc/config/frv/frv-protos.h
index 68c2a576a63..af9f1cdd7e2 100644
--- a/gcc/config/frv/frv-protos.h
+++ b/gcc/config/frv/frv-protos.h
@@ -53,13 +53,6 @@ extern void frv_init_cumulative_args (CUMULATIVE_ARGS *, tree,
rtx, tree, int);
extern int frv_function_arg_boundary (enum machine_mode, tree);
-extern rtx frv_function_arg (CUMULATIVE_ARGS *,
- enum machine_mode,
- tree, int, int);
-
-extern void frv_function_arg_advance (CUMULATIVE_ARGS *,
- enum machine_mode,
- tree, int);
extern bool frv_function_value_regno_p (const unsigned int);
#endif /* TREE_CODE */
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 4cbcfcac8a1..adc69117c4b 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -388,6 +388,12 @@ static rtx frv_struct_value_rtx (tree, int);
static bool frv_must_pass_in_stack (enum machine_mode mode, const_tree type);
static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
+static rtx frv_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
+static rtx frv_function_incoming_arg (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
+static void frv_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
static void frv_output_dwarf_dtprel (FILE *, int, rtx)
ATTRIBUTE_UNUSED;
static reg_class_t frv_secondary_reload (bool, rtx, reg_class_t,
@@ -486,6 +492,12 @@ static const struct default_options frv_option_optimization_table[] =
#define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES frv_arg_partial_bytes
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG frv_function_arg
+#undef TARGET_FUNCTION_INCOMING_ARG
+#define TARGET_FUNCTION_INCOMING_ARG frv_function_incoming_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE frv_function_arg_advance
#undef TARGET_EXPAND_BUILTIN_SAVEREGS
#define TARGET_EXPAND_BUILTIN_SAVEREGS frv_expand_builtin_saveregs
@@ -3190,12 +3202,10 @@ frv_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
return BITS_PER_WORD;
}
-rtx
-frv_function_arg (CUMULATIVE_ARGS *cum,
- enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED,
- int named,
- int incoming ATTRIBUTE_UNUSED)
+static rtx
+frv_function_arg_1 (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type ATTRIBUTE_UNUSED, bool named,
+ bool incoming ATTRIBUTE_UNUSED)
{
enum machine_mode xmode = (mode == BLKmode) ? SImode : mode;
int arg_num = *cum;
@@ -3229,6 +3239,20 @@ frv_function_arg (CUMULATIVE_ARGS *cum,
return ret;
}
+static rtx
+frv_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ return frv_function_arg_1 (cum, mode, type, named, false);
+}
+
+static rtx
+frv_function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ return frv_function_arg_1 (cum, mode, type, named, true);
+}
+
/* A C statement (sans semicolon) to update the summarizer variable CUM to
advance past an argument in the argument list. The values MODE, TYPE and
@@ -3239,11 +3263,11 @@ frv_function_arg (CUMULATIVE_ARGS *cum,
the stack. The compiler knows how to track the amount of stack space used
for arguments without any special help. */
-void
+static void
frv_function_arg_advance (CUMULATIVE_ARGS *cum,
enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED,
- int named)
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named)
{
enum machine_mode xmode = (mode == BLKmode) ? SImode : mode;
int bytes = GET_MODE_SIZE (xmode);
diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h
index 99e66434a89..fc0f2930dc3 100644
--- a/gcc/config/frv/frv.h
+++ b/gcc/config/frv/frv.h
@@ -1546,23 +1546,6 @@ typedef struct frv_stack {
#define FRV_NUM_ARG_REGS 6
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- frv_function_arg (&CUM, MODE, TYPE, NAMED, FALSE)
-
-/* Define this macro if the target machine has "register windows", so that the
- register in which a function sees an arguments is not necessarily the same
- as the one in which the caller passed the argument.
-
- For such machines, `FUNCTION_ARG' computes the register in which the caller
- passes the value, and `FUNCTION_INCOMING_ARG' should be defined in a similar
- fashion to tell the function being called where the arguments will arrive.
-
- If `FUNCTION_INCOMING_ARG' is not defined, `FUNCTION_ARG' serves both
- purposes. */
-
-#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
- frv_function_arg (&CUM, MODE, TYPE, NAMED, TRUE)
-
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the type
`int' suffices and can hold the number of bytes of argument so far.
@@ -1605,17 +1588,6 @@ typedef struct frv_stack {
#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
frv_init_cumulative_args (&CUM, FNTYPE, LIBNAME, NULL, TRUE)
-/* A C statement (sans semicolon) to update the summarizer variable CUM to
- advance past an argument in the argument list. The values MODE, TYPE and
- NAMED describe that argument. Once this is done, the variable CUM is
- suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
-
- This macro need not do anything if the argument in question was passed on
- the stack. The compiler knows how to track the amount of stack space used
- for arguments without any special help. */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- frv_function_arg_advance (&CUM, MODE, TYPE, NAMED)
-
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. If it is not defined,
`PARM_BOUNDARY' is used for all arguments. */
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index 7bf8ba367bd..676b3b7018e 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -89,8 +89,6 @@ extern int h8300_ldm_stm_parallel (rtvec, int, int);
#endif /* RTX_CODE */
#ifdef TREE_CODE
-extern struct rtx_def *function_arg (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
extern int h8300_funcvec_function_p (tree);
extern int h8300_eightbit_data_p (tree);
extern int h8300_tiny_data_p (tree);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index b9bc95caccf..f9bcc74732c 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -1095,11 +1095,14 @@ h8300_pr_saveall (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
/* If the next function argument with MODE and TYPE is to be passed in
a register, return a reg RTX for the hard register in which to pass
the argument. CUM represents the state after the last argument.
- If the argument is to be pushed, NULL_RTX is returned. */
+ If the argument is to be pushed, NULL_RTX is returned.
-rtx
-function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named)
+ On the H8/300 all normal args are pushed, unless -mquickcall in which
+ case the first 3 arguments are passed in registers. */
+
+static rtx
+h8300_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
{
static const char *const hand_list[] = {
"__main",
@@ -1163,6 +1166,20 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return result;
}
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+static void
+h8300_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ cum->nbytes += (mode != BLKmode
+ ? (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD
+ : (int_size_in_bytes (type) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD);
+}
+
/* Compute the cost of an and insn. */
@@ -5915,6 +5932,12 @@ h8300_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY h8300_return_in_memory
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG h8300_function_arg
+
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE h8300_function_arg_advance
+
#undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG h8300_reorg
diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h
index 593106b960d..eb747ed348d 100644
--- a/gcc/config/h8300/h8300.h
+++ b/gcc/config/h8300/h8300.h
@@ -600,35 +600,6 @@ struct cum_arg
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
((CUM).nbytes = 0, (CUM).libcall = LIBNAME)
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- ((CUM).nbytes += ((MODE) != BLKmode \
- ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD \
- : (int_size_in_bytes (TYPE) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD))
-
-/* Define where to put the arguments to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-
-/* On the H8/300 all normal args are pushed, unless -mquickcall in which
- case the first 3 arguments are passed in registers.
- See function `function_arg'. */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- function_arg (&CUM, MODE, TYPE, NAMED)
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f2bd70555dc..4cd3f070b91 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6952,10 +6952,12 @@ ix86_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
return 0;
}
-/* Return true when TYPE should be 128bit aligned for 32bit argument passing
- ABI. */
+/* Return true when TYPE should be 128bit aligned for 32bit argument
+ passing ABI. XXX: This function is obsolete and is only used for
+ checking psABI compatibility with previous versions of GCC. */
+
static bool
-contains_aligned_value_p (const_tree type)
+ix86_compat_aligned_value_p (const_tree type)
{
enum machine_mode mode = TYPE_MODE (type);
if (((TARGET_SSE && SSE_REG_MODE_P (mode))
@@ -6982,7 +6984,7 @@ contains_aligned_value_p (const_tree type)
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
if (TREE_CODE (field) == FIELD_DECL
- && contains_aligned_value_p (TREE_TYPE (field)))
+ && ix86_compat_aligned_value_p (TREE_TYPE (field)))
return true;
}
break;
@@ -6990,7 +6992,7 @@ contains_aligned_value_p (const_tree type)
case ARRAY_TYPE:
/* Just for use if some languages passes arrays by value. */
- if (contains_aligned_value_p (TREE_TYPE (type)))
+ if (ix86_compat_aligned_value_p (TREE_TYPE (type)))
return true;
break;
@@ -7001,9 +7003,13 @@ contains_aligned_value_p (const_tree type)
return false;
}
+/* Return the alignment boundary for MODE and TYPE with alignment ALIGN.
+ XXX: This function is obsolete and is only used for checking psABI
+ compatibility with previous versions of GCC. */
+
static int
-ix86_old_function_arg_boundary (enum machine_mode mode, const_tree type,
- int align)
+ix86_compat_function_arg_boundary (enum machine_mode mode,
+ const_tree type, int align)
{
/* In 32bit, only _Decimal128 and __float128 are aligned to their
natural boundaries. */
@@ -7023,7 +7029,7 @@ ix86_old_function_arg_boundary (enum machine_mode mode, const_tree type,
}
else
{
- if (!contains_aligned_value_p (type))
+ if (!ix86_compat_aligned_value_p (type))
align = PARM_BOUNDARY;
}
}
@@ -7032,6 +7038,59 @@ ix86_old_function_arg_boundary (enum machine_mode mode, const_tree type,
return align;
}
+/* Return true when TYPE should be 128bit aligned for 32bit argument
+ passing ABI. */
+
+static bool
+ix86_contains_aligned_value_p (const_tree type)
+{
+ enum machine_mode mode = TYPE_MODE (type);
+
+ if (mode == XFmode || mode == XCmode)
+ return false;
+
+ if (TYPE_ALIGN (type) < 128)
+ return false;
+
+ if (AGGREGATE_TYPE_P (type))
+ {
+ /* Walk the aggregates recursively. */
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ {
+ tree field;
+
+ /* Walk all the structure fields. */
+ for (field = TYPE_FIELDS (type);
+ field;
+ field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) == FIELD_DECL
+ && ix86_contains_aligned_value_p (TREE_TYPE (field)))
+ return true;
+ }
+ break;
+ }
+
+ case ARRAY_TYPE:
+ /* Just for use if some languages passes arrays by value. */
+ if (ix86_contains_aligned_value_p (TREE_TYPE (type)))
+ return true;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ return TYPE_ALIGN (type) >= 128;
+
+ return false;
+}
+
/* Gives the alignment boundary, in bits, of an argument with the
specified mode and type. */
@@ -7055,13 +7114,25 @@ ix86_function_arg_boundary (enum machine_mode mode, const_tree type)
static bool warned;
int saved_align = align;
- if (!TARGET_64BIT && align < 128)
- align = PARM_BOUNDARY;
+ if (!TARGET_64BIT)
+ {
+ /* i386 ABI defines XFmode arguments to be 4 byte aligned. */
+ if (!type)
+ {
+ if (mode == XFmode || mode == XCmode)
+ align = PARM_BOUNDARY;
+ }
+ else if (!ix86_contains_aligned_value_p (type))
+ align = PARM_BOUNDARY;
+
+ if (align < 128)
+ align = PARM_BOUNDARY;
+ }
if (warn_psabi
&& !warned
- && align != ix86_old_function_arg_boundary (mode, type,
- saved_align))
+ && align != ix86_compat_function_arg_boundary (mode, type,
+ saved_align))
{
warned = true;
inform (input_location,
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 078fac6c0f1..c359aed0791 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -3244,7 +3244,17 @@
(const_int 2)
(const_int 3)])))]
"TARGET_SSE"
- "ix86_fixup_binary_operands (UNKNOWN, V4SFmode, operands);")
+{
+ rtx dst = ix86_fixup_binary_operands (UNKNOWN, V4SFmode, operands);
+
+ emit_insn (gen_sse_movhlps (dst, operands[1], operands[2]));
+
+ /* Fix up the destination if needed. */
+ if (dst != operands[0])
+ emit_move_insn (operands[0], dst);
+
+ DONE;
+})
(define_insn "*avx_movhlps"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
@@ -3294,7 +3304,17 @@
(const_int 4)
(const_int 5)])))]
"TARGET_SSE"
- "ix86_fixup_binary_operands (UNKNOWN, V4SFmode, operands);")
+{
+ rtx dst = ix86_fixup_binary_operands (UNKNOWN, V4SFmode, operands);
+
+ emit_insn (gen_sse_movlhps (dst, operands[1], operands[2]));
+
+ /* Fix up the destination if needed. */
+ if (dst != operands[0])
+ emit_move_insn (operands[0], dst);
+
+ DONE;
+})
(define_insn "*avx_movlhps"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,o")
@@ -3701,7 +3721,17 @@
(parallel [(const_int 0) (const_int 1)]))
(match_operand:V2SF 2 "nonimmediate_operand" "")))]
"TARGET_SSE"
- "ix86_fixup_binary_operands (UNKNOWN, V4SFmode, operands);")
+{
+ rtx dst = ix86_fixup_binary_operands (UNKNOWN, V4SFmode, operands);
+
+ emit_insn (gen_sse_loadhps (dst, operands[1], operands[2]));
+
+ /* Fix up the destination if needed. */
+ if (dst != operands[0])
+ emit_move_insn (operands[0], dst);
+
+ DONE;
+})
(define_insn "*avx_loadhps"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,o")
@@ -3769,7 +3799,17 @@
(match_operand:V4SF 1 "nonimmediate_operand" "")
(parallel [(const_int 2) (const_int 3)]))))]
"TARGET_SSE"
- "ix86_fixup_binary_operands (UNKNOWN, V4SFmode, operands);")
+{
+ rtx dst = ix86_fixup_binary_operands (UNKNOWN, V4SFmode, operands);
+
+ emit_insn (gen_sse_loadlps (dst, operands[1], operands[2]));
+
+ /* Fix up the destination if needed. */
+ if (dst != operands[0])
+ emit_move_insn (operands[0], dst);
+
+ DONE;
+})
(define_insn "*avx_loadlps"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
@@ -4898,7 +4938,17 @@
(parallel [(const_int 0)]))
(match_operand:DF 2 "nonimmediate_operand" "")))]
"TARGET_SSE2"
- "ix86_fixup_binary_operands (UNKNOWN, V2DFmode, operands);")
+{
+ rtx dst = ix86_fixup_binary_operands (UNKNOWN, V2DFmode, operands);
+
+ emit_insn (gen_sse2_loadhpd (dst, operands[1], operands[2]));
+
+ /* Fix up the destination if needed. */
+ if (dst != operands[0])
+ emit_move_insn (operands[0], dst);
+
+ DONE;
+})
;; Avoid combining registers from different units in a single alternative,
;; see comment above inline_secondary_memory_needed function in i386.c
@@ -4957,7 +5007,17 @@
(match_operand:V2DF 1 "nonimmediate_operand" "")
(parallel [(const_int 1)]))))]
"TARGET_SSE2"
- "ix86_fixup_binary_operands (UNKNOWN, V2DFmode, operands);")
+{
+ rtx dst = ix86_fixup_binary_operands (UNKNOWN, V2DFmode, operands);
+
+ emit_insn (gen_sse2_loadlpd (dst, operands[1], operands[2]));
+
+ /* Fix up the destination if needed. */
+ if (dst != operands[0])
+ emit_move_insn (operands[0], dst);
+
+ DONE;
+})
;; Avoid combining registers from different units in a single alternative,
;; see comment above inline_secondary_memory_needed function in i386.c
diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h
index 1a9bd87f724..d2393bc8ccf 100644
--- a/gcc/config/ia64/ia64-protos.h
+++ b/gcc/config/ia64/ia64-protos.h
@@ -63,14 +63,10 @@ extern const char *get_bundle_name (int);
#ifdef TREE_CODE
#ifdef RTX_CODE
-extern rtx ia64_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
- tree, int, int);
extern rtx ia64_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
extern rtx ia64_va_arg (tree, tree);
#endif /* RTX_CODE */
-extern void ia64_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
- tree, int);
extern int ia64_function_arg_boundary (enum machine_mode, tree);
extern void ia64_asm_output_external (FILE *, tree, const char *);
extern void ia64_vms_output_aligned_decl_common (FILE *, tree, const char *,
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 96031504f3f..4a738095c6e 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -209,6 +209,14 @@ static void ia64_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
tree, int *, int);
static int ia64_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
+static rtx ia64_function_arg_1 (const CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool, bool);
+static rtx ia64_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
+static rtx ia64_function_incoming_arg (CUMULATIVE_ARGS *,
+ enum machine_mode, const_tree, bool);
+static void ia64_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+ const_tree, bool);
static bool ia64_function_ok_for_sibcall (tree, tree);
static bool ia64_return_in_memory (const_tree, const_tree);
static rtx ia64_function_value (const_tree, const_tree, bool);
@@ -325,6 +333,7 @@ static void ia64_dwarf_handle_frame_unspec (const char *, rtx, int);
static tree ia64_builtin_decl (unsigned, bool);
static reg_class_t ia64_preferred_reload_class (rtx, reg_class_t);
+static enum machine_mode ia64_get_reg_raw_mode (int regno);
/* Table of valid machine attributes. */
static const struct attribute_spec ia64_attribute_table[] =
@@ -481,6 +490,12 @@ static const struct default_options ia64_option_optimization_table[] =
#define TARGET_FUNCTION_OK_FOR_SIBCALL ia64_function_ok_for_sibcall
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES ia64_arg_partial_bytes
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG ia64_function_arg
+#undef TARGET_FUNCTION_INCOMING_ARG
+#define TARGET_FUNCTION_INCOMING_ARG ia64_function_incoming_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE ia64_function_arg_advance
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
@@ -545,6 +560,10 @@ static const struct default_options ia64_option_optimization_table[] =
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+#undef TARGET_GET_RAW_RESULT_MODE
+#define TARGET_GET_RAW_RESULT_MODE ia64_get_reg_raw_mode
+#undef TARGET_GET_RAW_ARG_MODE
+#define TARGET_GET_RAW_ARG_MODE ia64_get_reg_raw_mode
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
@@ -4250,7 +4269,7 @@ hfa_element_mode (const_tree type, bool nested)
/* Return the number of words required to hold a quantity of TYPE and MODE
when passed as an argument. */
static int
-ia64_function_arg_words (tree type, enum machine_mode mode)
+ia64_function_arg_words (const_tree type, enum machine_mode mode)
{
int words;
@@ -4276,7 +4295,8 @@ ia64_function_arg_words (tree type, enum machine_mode mode)
all as if they had 16 byte alignment. Such aggregates can occur
only if gcc extensions are used. */
static int
-ia64_function_arg_offset (CUMULATIVE_ARGS *cum, tree type, int words)
+ia64_function_arg_offset (const CUMULATIVE_ARGS *cum,
+ const_tree type, int words)
{
/* No registers are skipped on VMS. */
if (TARGET_ABI_OPEN_VMS || (cum->words & 1) == 0)
@@ -4295,9 +4315,9 @@ ia64_function_arg_offset (CUMULATIVE_ARGS *cum, tree type, int words)
/* ??? 128-bit quad-precision floats are always passed in general
registers. */
-rtx
-ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
- int named, int incoming)
+static rtx
+ia64_function_arg_1 (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named, bool incoming)
{
int basereg = (incoming ? GR_ARG_FIRST : AR_ARG_FIRST);
int words = ia64_function_arg_words (type, mode);
@@ -4486,6 +4506,25 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
}
}
+/* Implement TARGET_FUNCION_ARG target hook. */
+
+static rtx
+ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ return ia64_function_arg_1 (cum, mode, type, named, false);
+}
+
+/* Implement TARGET_FUNCION_INCOMING_ARG target hook. */
+
+static rtx
+ia64_function_incoming_arg (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode,
+ const_tree type, bool named)
+{
+ return ia64_function_arg_1 (cum, mode, type, named, true);
+}
+
/* Return number of bytes, at the beginning of the argument, that must be
put in registers. 0 is the argument is entirely in registers or entirely
in memory. */
@@ -4531,9 +4570,9 @@ ia64_arg_type (enum machine_mode mode)
/* Update CUM to point after this argument. This is patterned after
ia64_function_arg. */
-void
+static void
ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named)
+ const_tree type, bool named)
{
int words = ia64_function_arg_words (type, mode);
int offset = ia64_function_arg_offset (cum, type, words);
@@ -10959,5 +10998,12 @@ ia64_dconst_0_375 (void)
return ia64_dconst_0_375_rtx;
}
+static enum machine_mode
+ia64_get_reg_raw_mode (int regno)
+{
+ if (FR_REGNO_P (regno))
+ return XFmode;
+ return default_get_reg_raw_mode(regno);
+}
#include "gt-ia64.h"
diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
index 6fdcb97bcd6..fbee1e719b6 100644
--- a/gcc/config/ia64/ia64.h
+++ b/gcc/config/ia64/ia64.h
@@ -1026,19 +1026,6 @@ enum reg_class
#define FR_RET_LAST FR_REG (15)
#define AR_ARG_FIRST OUT_REG (0)
-/* A C expression that controls whether a function argument is passed in a
- register, and which register. */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ia64_function_arg (&CUM, MODE, TYPE, NAMED, 0)
-
-/* Define this macro if the target machine has "register windows", so that the
- register in which a function sees an arguments is not necessarily the same
- as the one in which the caller passed the argument. */
-
-#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
- ia64_function_arg (&CUM, MODE, TYPE, NAMED, 1)
-
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the type
`int' suffices and can hold the number of bytes of argument so far. */
@@ -1086,14 +1073,6 @@ do { \
(CUM).atypes[6] = (CUM).atypes[7] = I64; \
} while (0)
-/* A C statement (sans semicolon) to update the summarizer variable CUM to
- advance past an argument in the argument list. The values MODE, TYPE and
- NAMED describe that argument. Once this is done, the variable CUM is
- suitable for analyzing the *following* argument with `FUNCTION_ARG'. */
-
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- ia64_function_arg_advance (&CUM, MODE, TYPE, NAMED)
-
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. */
diff --git a/gcc/config/iq2000/iq2000-protos.h b/gcc/config/iq2000/iq2000-protos.h
index 971aadf4547..067e80747d1 100644
--- a/gcc/config/iq2000/iq2000-protos.h
+++ b/gcc/config/iq2000/iq2000-protos.h
@@ -42,8 +42,6 @@ extern void gen_conditional_branch (rtx *, enum machine_mode);
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
-extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
-extern struct rtx_def * function_arg (CUMULATIVE_ARGS *, enum machine_mode, const_tree, int);
extern bool iq2000_function_value_regno_p (const unsigned int);
#endif
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index f6caf6084a1..5661fd4eb8f 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -164,6 +164,10 @@ static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
const_tree, bool);
static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
+static rtx iq2000_function_arg (CUMULATIVE_ARGS *,
+ enum machine_mode, const_tree, bool);
+static void iq2000_function_arg_advance (CUMULATIVE_ARGS *,
+ enum machine_mode, const_tree, bool);
static void iq2000_va_start (tree, rtx);
static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool);
static bool iq2000_can_eliminate (const int, const int);
@@ -233,6 +237,10 @@ static const struct default_options iq2000_option_optimization_table[] =
#define TARGET_CALLEE_COPIES hook_callee_copies_named
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG iq2000_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE iq2000_function_arg_advance
#undef TARGET_SETUP_INCOMING_VARARGS
#define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs
@@ -1132,9 +1140,9 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
/* Advance the argument of type TYPE and mode MODE to the next argument
position in CUM. */
-void
-function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
- int named)
+static void
+iq2000_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
{
if (TARGET_DEBUG_D_MODE)
{
@@ -1201,9 +1209,9 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
/* Return an RTL expression containing the register for the given mode MODE
and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */
-struct rtx_def *
-function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, const_tree type,
- int named)
+static rtx
+iq2000_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
{
rtx ret;
int regbase = -1;
@@ -1939,9 +1947,11 @@ iq2000_expand_prologue (void)
passed_mode = Pmode;
}
- entry_parm = FUNCTION_ARG (args_so_far, passed_mode, passed_type, 1);
+ entry_parm = iq2000_function_arg (&args_so_far, passed_mode,
+ passed_type, true);
- FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, passed_type, 1);
+ iq2000_function_arg_advance (&args_so_far, passed_mode,
+ passed_type, true);
next_arg = DECL_CHAIN (cur_arg);
if (entry_parm && store_args_on_stack)
@@ -1980,10 +1990,11 @@ iq2000_expand_prologue (void)
/* In order to pass small structures by value in registers we need to
shift the value into the high part of the register.
- Function_arg has encoded a PARALLEL rtx, holding a vector of
- adjustments to be made as the next_arg_reg variable, so we split up the
- insns, and emit them separately. */
- next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
+ iq2000_unction_arg has encoded a PARALLEL rtx, holding a vector of
+ adjustments to be made as the next_arg_reg variable, so we split up
+ the insns, and emit them separately. */
+ next_arg_reg = iq2000_function_arg (&args_so_far, VOIDmode,
+ void_type_node, true);
if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
{
rtvec adjust = XVEC (next_arg_reg, 0);
@@ -2293,7 +2304,7 @@ iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
CUMULATIVE_ARGS temp;
temp = *cum;
- if (FUNCTION_ARG (temp, mode, type, named) != 0)
+ if (iq2000_function_arg (&temp, mode, type, named) != 0)
return 1;
}
diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h
index 91c5173416d..716be5b7a67 100644
--- a/gcc/config/iq2000/iq2000.h
+++ b/gcc/config/iq2000/iq2000.h
@@ -359,9 +359,6 @@ enum reg_class
/* Function Arguments in Registers. */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- function_arg (& CUM, MODE, TYPE, NAMED)
-
#define MAX_ARGS_IN_REGISTERS 8
typedef struct iq2000_args
@@ -383,9 +380,6 @@ typedef struct iq2000_args
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
init_cumulative_args (& CUM, FNTYPE, LIBNAME) \
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- function_arg_advance (& CUM, MODE, TYPE, NAMED)
-
#define FUNCTION_ARG_PADDING(MODE, TYPE) \
(! BYTES_BIG_ENDIAN \
? upward \
diff --git a/gcc/config/lm32/lm32-protos.h b/gcc/config/lm32/lm32-protos.h
index 51e191bab81..bc086d2ee0b 100644
--- a/gcc/config/lm32/lm32-protos.h
+++ b/gcc/config/lm32/lm32-protos.h
@@ -26,8 +26,6 @@ extern void lm32_expand_prologue (void);
extern void lm32_expand_epilogue (void);
extern void lm32_print_operand (FILE *file, rtx op, int letter);
extern void lm32_print_operand_address (FILE *file, rtx addr);
-extern rtx lm32_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
- tree type, int named);
extern HOST_WIDE_INT lm32_compute_initial_elimination_offset (int from,
int to);
extern int lm32_can_use_return (void);
diff --git a/gcc/config/lm32/lm32.c b/gcc/config/lm32/lm32.c
index bcab220613d..18a4b4403cd 100644
--- a/gcc/config/lm32/lm32.c
+++ b/gcc/config/lm32/lm32.c
@@ -76,6 +76,12 @@ static bool
lm32_legitimate_address_p (enum machine_mode mode, rtx x, bool strict);
static HOST_WIDE_INT lm32_compute_frame_size (int size);
static void lm32_option_override (void);
+static rtx lm32_function_arg (CUMULATIVE_ARGS * cum,
+ enum machine_mode mode, const_tree type,
+ bool named);
+static void lm32_function_arg_advance (CUMULATIVE_ARGS * cum,
+ enum machine_mode mode,
+ const_tree type, bool named);
/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
static const struct default_options lm32_option_optimization_table[] =
@@ -98,6 +104,10 @@ static const struct default_options lm32_option_optimization_table[] =
#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
#undef TARGET_SETUP_INCOMING_VARARGS
#define TARGET_SETUP_INCOMING_VARARGS lm32_setup_incoming_varargs
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG lm32_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE lm32_function_arg_advance
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
#undef TARGET_MIN_ANCHOR_OFFSET
@@ -613,9 +623,9 @@ lm32_print_operand_address (FILE * file, rtx addr)
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis). */
-rtx
-lm32_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
- tree type, int named)
+static rtx
+lm32_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
{
if (mode == VOIDmode)
/* Compute operand 2 of the call insn. */
@@ -624,10 +634,17 @@ lm32_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
if (targetm.calls.must_pass_in_stack (mode, type))
return NULL_RTX;
- if (!named || (cum + LM32_NUM_REGS2 (mode, type) > LM32_NUM_ARG_REGS))
+ if (!named || (*cum + LM32_NUM_REGS2 (mode, type) > LM32_NUM_ARG_REGS))
return NULL_RTX;
- return gen_rtx_REG (mode, cum + LM32_FIRST_ARG_REG);
+ return gen_rtx_REG (mode, *cum + LM32_FIRST_ARG_REG);
+}
+
+static void
+lm32_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ *cum += LM32_NUM_REGS2 (mode, type);
}
HOST_WIDE_INT
diff --git a/gcc/config/lm32/lm32.h b/gcc/config/lm32/lm32.h
index cec835106a9..bcea41aa3a1 100644
--- a/gcc/config/lm32/lm32.h
+++ b/gcc/config/lm32/lm32.h
@@ -276,17 +276,11 @@ enum reg_class
/* The number of (integer) argument register available. */
#define LM32_NUM_ARG_REGS 8
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- lm32_function_arg ((CUM), (MODE), (TYPE), (NAMED))
-
#define CUMULATIVE_ARGS int
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT,N_NAMED_ARGS) \
(CUM) = 0
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (CUM) += LM32_NUM_REGS2 (MODE, TYPE)
-
#define FUNCTION_ARG_REGNO_P(r) \
(((r) >= LM32_FIRST_ARG_REG) && ((r) <= LM32_NUM_ARG_REGS))
diff --git a/gcc/config/m68hc11/m68hc11-protos.h b/gcc/config/m68hc11/m68hc11-protos.h
index e98c1909baf..08e0b4d9b13 100644
--- a/gcc/config/m68hc11/m68hc11-protos.h
+++ b/gcc/config/m68hc11/m68hc11-protos.h
@@ -31,13 +31,6 @@ extern int m68hc11_initial_elimination_offset (int, int);
extern void expand_prologue (void);
extern void expand_epilogue (void);
-#ifdef TREE_CODE
-extern void m68hc11_function_arg_advance (CUMULATIVE_ARGS*,
- enum machine_mode,
- tree,
- int);
-#endif
-
#ifdef RTX_CODE
extern int m68hc11_auto_inc_p (rtx);
@@ -98,9 +91,6 @@ extern int soft_reg_operand (rtx, enum machine_mode);
extern void m68hc11_init_cumulative_args (CUMULATIVE_ARGS*, tree, rtx);
-extern rtx m68hc11_function_arg (const CUMULATIVE_ARGS* ,
- enum machine_mode,
- tree, int);
#ifdef ARGS_SIZE_RTX
extern enum direction m68hc11_function_arg_padding (enum machine_mode,
const_tree);
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c
index e45a74892c6..6e11a080bb2 100644
--- a/gcc/config/m68hc11/m68hc11.c
+++ b/gcc/config/m68hc11/m68hc11.c
@@ -98,6 +98,11 @@ static bool m68hc11_return_in_memory (const_tree, const_tree);
static bool m68hc11_can_eliminate (const int, const int);
static void m68hc11_trampoline_init (rtx, tree, rtx);
+static rtx m68hc11_function_arg (CUMULATIVE_ARGS*, enum machine_mode,
+ const_tree, bool);
+static void m68hc11_function_arg_advance (CUMULATIVE_ARGS*, enum machine_mode,
+ const_tree, bool);
+
/* Must be set to 1 to produce debug messages. */
int debug_m6811 = 0;
@@ -276,6 +281,11 @@ static const struct attribute_spec m68hc11_attribute_table[] =
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS m68hc11_init_libfuncs
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG m68hc11_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE m68hc11_function_arg_advance
+
#undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX m68hc11_struct_value_rtx
#undef TARGET_RETURN_IN_MEMORY
@@ -1477,9 +1487,9 @@ m68hc11_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname)
of mode MODE and data type TYPE.
(TYPE is null for libcalls where that information may not be available.) */
-void
+static void
m68hc11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named ATTRIBUTE_UNUSED)
+ const_tree type, bool named ATTRIBUTE_UNUSED)
{
if (mode != BLKmode)
{
@@ -1515,9 +1525,10 @@ m68hc11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis). */
-struct rtx_def *
-m68hc11_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
+static rtx
+m68hc11_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
{
if (cum->words != 0)
{
diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h
index 9e45cb51496..8e817c824a0 100644
--- a/gcc/config/m68hc11/m68hc11.h
+++ b/gcc/config/m68hc11/m68hc11.h
@@ -890,27 +890,6 @@ typedef struct m68hc11_args
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
(m68hc11_init_cumulative_args (&CUM, FNTYPE, LIBNAME))
-/* Update the data in CUM to advance over an argument of mode MODE and data
- type TYPE. (TYPE is null for libcalls where that information may not be
- available.) */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (m68hc11_function_arg_advance (&CUM, MODE, TYPE, NAMED))
-
-/* Define where to put the arguments to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- (m68hc11_function_arg (&CUM, MODE, TYPE, NAMED))
-
/* Define the profitability of saving registers around calls.
Disable this because the saving instructions generated by
diff --git a/gcc/config/mcore/mcore-protos.h b/gcc/config/mcore/mcore-protos.h
index 2093f16ec19..b9f8f330737 100644
--- a/gcc/config/mcore/mcore-protos.h
+++ b/gcc/config/mcore/mcore-protos.h
@@ -65,8 +65,5 @@ extern int mcore_arith_S_operand (rtx);
extern const char * mcore_output_move (rtx, rtx *, enum machine_mode);
extern const char * mcore_output_movedouble (rtx *, enum machine_mode);
extern int const_ok_for_mcore (HOST_WIDE_INT);
-#ifdef TREE_CODE
-extern rtx mcore_function_arg (CUMULATIVE_ARGS, enum machine_mode, tree, int);
-#endif /* TREE_CODE */
#endif /* HAVE_MACHINE_MODES */
#endif /* RTX_CODE */
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index 9bacc5caee0..3bd17299b11 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -142,6 +142,12 @@ static bool mcore_return_in_memory (const_tree, const_tree);
static int mcore_arg_partial_bytes (CUMULATIVE_ARGS *,
enum machine_mode,
tree, bool);
+static rtx mcore_function_arg (CUMULATIVE_ARGS *,
+ enum machine_mode,
+ const_tree, bool);
+static void mcore_function_arg_advance (CUMULATIVE_ARGS *,
+ enum machine_mode,
+ const_tree, bool);
static void mcore_asm_trampoline_template (FILE *);
static void mcore_trampoline_init (rtx, tree, rtx);
static void mcore_option_override (void);
@@ -229,6 +235,10 @@ static const struct default_options mcore_option_optimization_table[] =
#define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES mcore_arg_partial_bytes
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG mcore_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE mcore_function_arg_advance
#undef TARGET_SETUP_INCOMING_VARARGS
#define TARGET_SETUP_INCOMING_VARARGS mcore_setup_incoming_varargs
@@ -2804,9 +2814,9 @@ mcore_function_value (const_tree valtype, const_tree func)
NPARM_REGS words is at least partially passed in a register unless
its data type forbids. */
-rtx
-mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
- tree type, int named)
+static rtx
+mcore_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named)
{
int arg_reg;
@@ -2816,7 +2826,7 @@ mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
if (targetm.calls.must_pass_in_stack (mode, type))
return 0;
- arg_reg = ROUND_REG (cum, mode);
+ arg_reg = ROUND_REG (*cum, mode);
if (arg_reg < NPARM_REGS)
return handle_structs_in_regs (mode, type, FIRST_PARM_REG + arg_reg);
@@ -2824,6 +2834,14 @@ mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
return 0;
}
+static void
+mcore_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ *cum = (ROUND_REG (*cum, mode)
+ + (int)named * mcore_num_arg_regs (mode, type));
+}
+
/* Returns the number of bytes of argument registers required to hold *part*
of a parameter of machine mode MODE and type TYPE (which may be NULL if
the type is not known). If the argument fits entirely in the argument
diff --git a/gcc/config/mcore/mcore.h b/gcc/config/mcore/mcore.h
index 8efe64f2bf0..515865854ae 100644
--- a/gcc/config/mcore/mcore.h
+++ b/gcc/config/mcore/mcore.h
@@ -559,18 +559,6 @@ extern const enum reg_class reg_class_from_letter[];
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
((CUM) = 0)
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be
- available.) */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- ((CUM) = (ROUND_REG ((CUM), (MODE)) \
- + ((NAMED) * mcore_num_arg_regs (MODE, TYPE)))) \
-
-/* Define where to put the arguments to a function. */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- mcore_function_arg (CUM, MODE, TYPE, NAMED)
-
/* Call the function profiler with a given profile label. */
#define FUNCTION_PROFILER(STREAM,LABELNO) \
{ \
diff --git a/gcc/config/mn10300/mn10300-protos.h b/gcc/config/mn10300/mn10300-protos.h
index 23d428cec22..ebf915e8e7e 100644
--- a/gcc/config/mn10300/mn10300-protos.h
+++ b/gcc/config/mn10300/mn10300-protos.h
@@ -43,10 +43,6 @@ extern int mn10300_symbolic_operand (rtx, Mmode);
extern bool mn10300_wide_const_load_uses_clr (rtx operands[2]);
#endif /* RTX_CODE */
-#ifdef TREE_CODE
-extern struct rtx_def * mn10300_function_arg (CUMULATIVE_ARGS *, Mmode, tree, int);
-#endif /* TREE_CODE */
-
extern int mn10300_can_use_return_insn (void);
extern void mn10300_expand_prologue (void);
extern void mn10300_expand_epilogue (void);
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 2187463d083..c0f11805117 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -58,6 +58,12 @@ int mn10300_protect_label;
/* The selected processor. */
enum processor_type mn10300_processor = PROCESSOR_DEFAULT;
+/* Processor type to select for tuning. */
+static const char * mn10300_tune_string = NULL;
+
+/* Selected processor type for tuning. */
+enum processor_type mn10300_tune_cpu = PROCESSOR_DEFAULT;
+
/* The size of the callee register save area. Right now we save everything
on entry since it costs us nothing in code size. It does cost us from a
speed standpoint, so we want to optimize this sooner or later. */
@@ -91,11 +97,21 @@ mn10300_handle_option (size_t code,
case OPT_mam33:
mn10300_processor = value ? PROCESSOR_AM33 : PROCESSOR_MN10300;
return true;
+
case OPT_mam33_2:
mn10300_processor = (value
? PROCESSOR_AM33_2
: MIN (PROCESSOR_AM33, PROCESSOR_DEFAULT));
return true;
+
+ case OPT_mam34:
+ mn10300_processor = (value ? PROCESSOR_AM34 : PROCESSOR_DEFAULT);
+ return true;
+
+ case OPT_mtune_:
+ mn10300_tune_string = arg;
+ return true;
+
default:
return true;
}
@@ -108,6 +124,27 @@ mn10300_option_override (void)
{
if (TARGET_AM33)
target_flags &= ~MASK_MULT_BUG;
+ else
+ {
+ /* Disable scheduling for the MN10300 as we do
+ not have timing information available for it. */
+ flag_schedule_insns = 0;
+ flag_schedule_insns_after_reload = 0;
+ }
+
+ if (mn10300_tune_string)
+ {
+ if (strcasecmp (mn10300_tune_string, "mn10300") == 0)
+ mn10300_tune_cpu = PROCESSOR_MN10300;
+ else if (strcasecmp (mn10300_tune_string, "am33") == 0)
+ mn10300_tune_cpu = PROCESSOR_AM33;
+ else if (strcasecmp (mn10300_tune_string, "am33-2") == 0)
+ mn10300_tune_cpu = PROCESSOR_AM33_2;
+ else if (strcasecmp (mn10300_tune_string, "am34") == 0)
+ mn10300_tune_cpu = PROCESSOR_AM34;
+ else
+ error ("-mtune= expects mn10300, am33, am33-2, or am34");
+ }
}
static void
@@ -370,7 +407,7 @@ mn10300_print_operand (FILE *file, rtx x, int code)
case 'A':
fputc ('(', file);
- if (REG_P ((XEXP (x, 0))))
+ if (REG_P (XEXP (x, 0)))
output_address (gen_rtx_PLUS (SImode, XEXP (x, 0), const0_rtx));
else
output_address (XEXP (x, 0));
@@ -392,7 +429,7 @@ mn10300_print_operand (FILE *file, rtx x, int code)
shift count as an error. So we mask off the high bits
of the immediate here. */
case 'S':
- if (CONST_INT_P ((x)))
+ if (CONST_INT_P (x))
{
fprintf (file, "%d", (int)(INTVAL (x) & 0x1f));
break;
@@ -1250,8 +1287,8 @@ mn10300_secondary_reload_class (enum reg_class rclass, enum machine_mode mode,
/* Memory loads less than a full word wide can't have an
address or stack pointer destination. They must use
a data register as an intermediate register. */
- if ((MEM_P ((in))
- || (REG_P ((inner))
+ if ((MEM_P (in)
+ || (REG_P (inner)
&& REGNO (inner) >= FIRST_PSEUDO_REGISTER))
&& (mode == QImode || mode == HImode)
&& (rclass == ADDRESS_REGS || rclass == SP_REGS
@@ -1281,13 +1318,13 @@ mn10300_secondary_reload_class (enum reg_class rclass, enum machine_mode mode,
{
/* We can't load directly into an FP register from a
constant address. */
- if (MEM_P ((in))
+ if (MEM_P (in)
&& CONSTANT_ADDRESS_P (XEXP (in, 0)))
return DATA_OR_EXTENDED_REGS;
/* Handle case were a pseudo may not get a hard register
but has an equivalent memory location defined. */
- if (REG_P ((inner))
+ if (REG_P (inner)
&& REGNO (inner) >= FIRST_PSEUDO_REGISTER
&& reg_equiv_mem [REGNO (inner)]
&& CONSTANT_ADDRESS_P (XEXP (reg_equiv_mem [REGNO (inner)], 0)))
@@ -1417,9 +1454,9 @@ mn10300_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
/* Return an RTX to represent where a value with mode MODE will be returned
from a function. If the result is NULL_RTX, the argument is pushed. */
-rtx
+static rtx
mn10300_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named ATTRIBUTE_UNUSED)
+ const_tree type, bool named ATTRIBUTE_UNUSED)
{
rtx result = NULL_RTX;
int size, align;
@@ -1464,6 +1501,19 @@ mn10300_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return result;
}
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+static void
+mn10300_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ cum->nbytes += (mode != BLKmode
+ ? (GET_MODE_SIZE (mode) + 3) & ~3
+ : (int_size_in_bytes (type) + 3) & ~3);
+}
+
/* Return the number of bytes of registers to use for an argument passed
partially in registers and partially in memory. */
@@ -1683,7 +1733,7 @@ mn10300_symbolic_operand (rtx op,
op = XEXP (op, 0);
return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
|| GET_CODE (XEXP (op, 0)) == LABEL_REF)
- && CONST_INT_P ((XEXP (op, 1))));
+ && CONST_INT_P (XEXP (op, 1)));
default:
return 0;
}
@@ -1857,7 +1907,7 @@ mn10300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
if (base != 0 && index != 0)
{
- if (CONST_INT_P ((index)))
+ if (CONST_INT_P (index))
return TRUE;
if (GET_CODE (index) == CONST
&& GET_CODE (XEXP (index, 0)) != PLUS
@@ -1894,7 +1944,6 @@ mn10300_legitimate_constant_p (rtx x)
/* Only some unspecs are valid as "constants". */
if (GET_CODE (x) == UNSPEC)
{
- rtx sym = XVECEXP (x, 0, 0);
switch (XINT (x, 1))
{
case UNSPEC_INT_LABEL:
@@ -2057,7 +2106,7 @@ mn10300_wide_const_load_uses_clr (rtx operands[2])
{
long val[2] = {0, 0};
- if (! REG_P (operands[0])
+ if ((! REG_P (operands[0]))
|| REGNO_REG_CLASS (REGNO (operands[0])) != DATA_REGS)
return false;
@@ -2259,6 +2308,101 @@ mn10300_select_cc_mode (rtx x)
{
return (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) ? CC_FLOATmode : CCmode;
}
+
+static inline bool
+is_load_insn (rtx insn)
+{
+ if (GET_CODE (PATTERN (insn)) != SET)
+ return false;
+
+ return MEM_P (SET_SRC (PATTERN (insn)));
+}
+
+static inline bool
+is_store_insn (rtx insn)
+{
+ if (GET_CODE (PATTERN (insn)) != SET)
+ return false;
+
+ return MEM_P (SET_DEST (PATTERN (insn)));
+}
+
+/* Update scheduling costs for situations that cannot be
+ described using the attributes and DFA machinery.
+ DEP is the insn being scheduled.
+ INSN is the previous insn.
+ COST is the current cycle cost for DEP. */
+
+static int
+mn10300_adjust_sched_cost (rtx insn, rtx link, rtx dep, int cost)
+{
+ int timings = get_attr_timings (insn);
+
+ if (!TARGET_AM33)
+ return 1;
+
+ if (GET_CODE (insn) == PARALLEL)
+ insn = XVECEXP (insn, 0, 0);
+
+ if (GET_CODE (dep) == PARALLEL)
+ dep = XVECEXP (dep, 0, 0);
+
+ /* For the AM34 a load instruction that follows a
+ store instruction incurs an extra cycle of delay. */
+ if (mn10300_tune_cpu == PROCESSOR_AM34
+ && is_load_insn (dep)
+ && is_store_insn (insn))
+ cost += 1;
+
+ /* For the AM34 a non-store, non-branch FPU insn that follows
+ another FPU insn incurs a one cycle throughput increase. */
+ else if (mn10300_tune_cpu == PROCESSOR_AM34
+ && ! is_store_insn (insn)
+ && ! JUMP_P (insn)
+ && GET_CODE (PATTERN (dep)) == SET
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (dep)))) == MODE_FLOAT
+ && GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (insn)))) == MODE_FLOAT)
+ cost += 1;
+
+ /* Resolve the conflict described in section 1-7-4 of
+ Chapter 3 of the MN103E Series Instruction Manual
+ where it says:
+
+ "When the preceeding instruction is a CPU load or
+ store instruction, a following FPU instruction
+ cannot be executed until the CPU completes the
+ latency period even though there are no register
+ or flag dependencies between them." */
+
+ /* Only the AM33-2 (and later) CPUs have FPU instructions. */
+ if (! TARGET_AM33_2)
+ return cost;
+
+ /* If a data dependence already exists then the cost is correct. */
+ if (REG_NOTE_KIND (link) == 0)
+ return cost;
+
+ /* Check that the instruction about to scheduled is an FPU instruction. */
+ if (GET_CODE (PATTERN (dep)) != SET)
+ return cost;
+
+ if (GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (dep)))) != MODE_FLOAT)
+ return cost;
+
+ /* Now check to see if the previous instruction is a load or store. */
+ if (! is_load_insn (insn) && ! is_store_insn (insn))
+ return cost;
+
+ /* XXX: Verify: The text of 1-7-4 implies that the restriction
+ only applies when an INTEGER load/store preceeds an FPU
+ instruction, but is this true ? For now we assume that it is. */
+ if (GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (insn)))) != MODE_INT)
+ return cost;
+
+ /* Extract the latency value from the timings attribute. */
+ return timings < 100 ? (timings % 10) : (timings % 100);
+}
/* Initialize the GCC target structure. */
@@ -2303,6 +2447,10 @@ mn10300_select_cc_mode (rtx x)
#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES mn10300_arg_partial_bytes
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG mn10300_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE mn10300_function_arg_advance
#undef TARGET_EXPAND_BUILTIN_SAVEREGS
#define TARGET_EXPAND_BUILTIN_SAVEREGS mn10300_builtin_saveregs
@@ -2330,4 +2478,7 @@ mn10300_select_cc_mode (rtx x)
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK mn10300_can_output_mi_thunk
+#undef TARGET_SCHED_ADJUST_COST
+#define TARGET_SCHED_ADJUST_COST mn10300_adjust_sched_cost
+
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h
index 96a07e8fcdf..c9f76f87593 100644
--- a/gcc/config/mn10300/mn10300.h
+++ b/gcc/config/mn10300/mn10300.h
@@ -38,7 +38,12 @@
builtin_assert ("cpu=mn10300"); \
builtin_assert ("machine=mn10300"); \
\
- if (TARGET_AM33_2) \
+ if (TARGET_AM34) \
+ { \
+ builtin_define ("__AM33__=4"); \
+ builtin_define ("__AM34__"); \
+ } \
+ else if (TARGET_AM33_2) \
{ \
builtin_define ("__AM33__=2"); \
builtin_define ("__AM33_2__"); \
@@ -54,13 +59,16 @@ enum processor_type
{
PROCESSOR_MN10300,
PROCESSOR_AM33,
- PROCESSOR_AM33_2
+ PROCESSOR_AM33_2,
+ PROCESSOR_AM34
};
extern enum processor_type mn10300_processor;
+extern enum processor_type mn10300_tune_cpu;
#define TARGET_AM33 (mn10300_processor >= PROCESSOR_AM33)
-#define TARGET_AM33_2 (mn10300_processor == PROCESSOR_AM33_2)
+#define TARGET_AM33_2 (mn10300_processor >= PROCESSOR_AM33_2)
+#define TARGET_AM34 (mn10300_processor >= PROCESSOR_AM34)
#ifndef PROCESSOR_DEFAULT
#define PROCESSOR_DEFAULT PROCESSOR_MN10300
@@ -274,7 +282,7 @@ enum reg_class
/* Give names of register classes as strings for dump file. */
-#define REG_CLASS_NAMES \
+#define REG_CLASS_NAMES \
{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", \
"SP_REGS", "DATA_OR_ADDRESS_REGS", "SP_OR_ADDRESS_REGS", \
"EXTENDED_REGS", \
@@ -289,7 +297,7 @@ enum reg_class
of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \
-{ { 0, 0 }, /* No regs */ \
+{ { 0, 0 }, /* No regs */ \
{ 0x0000000f, 0 }, /* DATA_REGS */ \
{ 0x000001f0, 0 }, /* ADDRESS_REGS */ \
{ 0x00000200, 0 }, /* SP_REGS */ \
@@ -304,7 +312,7 @@ enum reg_class
{ 0x03fc0000, 0 }, /* FP_ACC_REGS */ \
{ 0x00000000, 0x80000 },/* CC_REGS */ \
{ 0x0003fdff, 0 }, /* GENERAL_REGS */ \
- { 0xffffffff, 0xfffff } /* ALL_REGS */ \
+ { 0xffffffff, 0xfffff } /* ALL_REGS */ \
}
/* The following macro defines cover classes for Integrated Register
@@ -534,31 +542,6 @@ struct cum_arg
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
((CUM).nbytes = 0)
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- ((CUM).nbytes += ((MODE) != BLKmode \
- ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
- : (int_size_in_bytes (TYPE) + 3) & ~3))
-
-/* Define where to put the arguments to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- mn10300_function_arg (&(CUM), MODE, TYPE, NAMED)
-
#define FUNCTION_VALUE_REGNO_P(N) mn10300_function_value_regno_p (N)
#define DEFAULT_PCC_STRUCT_RETURN 0
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
index d90f0f25836..26126a7c034 100644
--- a/gcc/config/mn10300/mn10300.md
+++ b/gcc/config/mn10300/mn10300.md
@@ -40,6 +40,114 @@
(include "predicates.md")
(include "constraints.md")
+
+;; Processor type. This attribute must exactly match the processor_type
+;; enumeration in mn10300.h.
+(define_attr "cpu" "mn10300,am33,am33_2,am34"
+ (const (symbol_ref "mn10300_tune_cpu")))
+
+
+;; Pipeline description.
+
+;; The AM33 only has a single pipeline. It has five stages (fetch,
+;; decode, execute, memory access, writeback) each of which normally
+;; takes a single CPU clock cycle.
+
+;; The timings attribute consists of two numbers, the first is the
+;; throughput, which is the number of cycles the instruction takes
+;; to execute and generate a result. The second is the latency
+;; which is the effective number of cycles the instruction takes to
+;; execute if its result is used by the following instruction. The
+;; latency is always greater than or equal to the throughput.
+;; These values were taken from the Appendix of the "MN103E Series
+;; Instruction Manual" and the timings for the AM34.
+
+;; Note - it would be nice to use strings rather than integers for
+;; the possible values of this attribute, so that we can have the
+;; gcc build mechanism check for values that are not supported by
+;; the reservations below. But this will not work because the code
+;; in mn10300_adjust_sched_cost() needs integers not strings.
+
+(define_attr "timings" "" (const_int 11))
+
+(define_automaton "pipelining")
+(define_cpu_unit "throughput" "pipelining")
+
+(define_insn_reservation "throughput__1_latency__1" 1
+ (eq_attr "timings" "11") "throughput")
+(define_insn_reservation "throughput__1_latency__2" 2
+ (eq_attr "timings" "12") "throughput,nothing")
+(define_insn_reservation "throughput__1_latency__3" 3
+ (eq_attr "timings" "13") "throughput,nothing*2")
+(define_insn_reservation "throughput__1_latency__4" 4
+ (eq_attr "timings" "14") "throughput,nothing*3")
+(define_insn_reservation "throughput__2_latency__2" 2
+ (eq_attr "timings" "22") "throughput*2")
+(define_insn_reservation "throughput__2_latency__3" 3
+ (eq_attr "timings" "23") "throughput*2,nothing")
+(define_insn_reservation "throughput__2_latency__4" 4
+ (eq_attr "timings" "24") "throughput*2,nothing*2")
+(define_insn_reservation "throughput__2_latency__5" 5
+ (eq_attr "timings" "25") "throughput*2,nothing*3")
+(define_insn_reservation "throughput__3_latency__3" 3
+ (eq_attr "timings" "33") "throughput*3")
+(define_insn_reservation "throughput__3_latency__7" 7
+ (eq_attr "timings" "37") "throughput*3,nothing*4")
+(define_insn_reservation "throughput__4_latency__4" 4
+ (eq_attr "timings" "44") "throughput*4")
+(define_insn_reservation "throughput__4_latency__7" 7
+ (eq_attr "timings" "47") "throughput*4,nothing*3")
+(define_insn_reservation "throughput__4_latency__8" 8
+ (eq_attr "timings" "48") "throughput*4,nothing*4")
+(define_insn_reservation "throughput__5_latency__5" 5
+ (eq_attr "timings" "55") "throughput*5")
+(define_insn_reservation "throughput__6_latency__6" 6
+ (eq_attr "timings" "66") "throughput*6")
+(define_insn_reservation "throughput__7_latency__7" 7
+ (eq_attr "timings" "77") "throughput*7")
+(define_insn_reservation "throughput__7_latency__8" 8
+ (eq_attr "timings" "78") "throughput*7,nothing")
+(define_insn_reservation "throughput__8_latency__8" 8
+ (eq_attr "timings" "88") "throughput*8")
+(define_insn_reservation "throughput__9_latency__9" 9
+ (eq_attr "timings" "99") "throughput*9")
+(define_insn_reservation "throughput__8_latency_14" 14
+ (eq_attr "timings" "814") "throughput*8,nothing*6")
+(define_insn_reservation "throughput__9_latency_10" 10
+ (eq_attr "timings" "910") "throughput*9,nothing")
+(define_insn_reservation "throughput_10_latency_10" 10
+ (eq_attr "timings" "1010") "throughput*10")
+(define_insn_reservation "throughput_12_latency_16" 16
+ (eq_attr "timings" "1216") "throughput*12,nothing*4")
+(define_insn_reservation "throughput_13_latency_13" 13
+ (eq_attr "timings" "1313") "throughput*13")
+(define_insn_reservation "throughput_14_latency_14" 14
+ (eq_attr "timings" "1414") "throughput*14")
+(define_insn_reservation "throughput_13_latency_17" 17
+ (eq_attr "timings" "1317") "throughput*13,nothing*4")
+(define_insn_reservation "throughput_23_latency_27" 27
+ (eq_attr "timings" "2327") "throughput*23,nothing*4")
+(define_insn_reservation "throughput_25_latency_31" 31
+ (eq_attr "timings" "2531") "throughput*25,nothing*6")
+(define_insn_reservation "throughput_38_latency_39" 39
+ (eq_attr "timings" "3839") "throughput*38,nothing")
+(define_insn_reservation "throughput_39_latency_40" 40
+ (eq_attr "timings" "3940") "throughput*39,nothing")
+(define_insn_reservation "throughput_40_latency_40" 40
+ (eq_attr "timings" "4040") "throughput*40")
+(define_insn_reservation "throughput_41_latency_42" 42
+ (eq_attr "timings" "4142") "throughput*41,nothing")
+(define_insn_reservation "throughput_43_latency_44" 44
+ (eq_attr "timings" "4344") "throughput*43,nothing")
+(define_insn_reservation "throughput_45_latency_46" 46
+ (eq_attr "timings" "4546") "throughput*45,nothing")
+(define_insn_reservation "throughput_47_latency_53" 53
+ (eq_attr "timings" "4753") "throughput*47,nothing*6")
+
+;; Note - the conflict between memory load/store instructions
+;; and floating point instructions described in section 1-7-4
+;; of Chapter 3 of the MN103E Series Instruction Manual is
+;; handled by the mn10300_adjust_sched_cost function.
;; ----------------------------------------------------------------------
;; MOVE INSTRUCTIONS
@@ -48,7 +156,7 @@
;; movqi
(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand")
+ [(set (match_operand:QI 0 "nonimmediate_operand")
(match_operand:QI 1 "general_operand"))]
""
"
@@ -60,52 +168,62 @@
}")
(define_insn "*am33_movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d*x*a*f,d*x*a,d*x*a,m,*f,d*x*a")
- (match_operand:QI 1 "general_operand" "0,d*xai,m,d*xa,d*xa*f,*f"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand"
+ ;; 0 1 2 3 4 5
+ "=d*x*a*f, d*x*a, d*x*a, m, *f, d*x*a")
+ (match_operand:QI 1 "general_operand"
+ "0, d*xai, m, d*xa, d*xa*f, *f"))]
"TARGET_AM33
&& (register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))"
"*
-{
- switch (which_alternative)
- {
- case 0:
- return \"nop\";
- case 1:
- if (CONST_DOUBLE_P (operands[1]))
- {
- rtx xoperands[2];
- xoperands[0] = operands[0];
- xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- output_asm_insn (\"mov %1,%0\", xoperands);
- return \"\";
- }
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return \"nop\";
+ case 1:
+ gcc_assert (! CONST_DOUBLE_P (operands[1]));
- if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
- && CONST_INT_P (operands[1]))
- {
- HOST_WIDE_INT val = INTVAL (operands[1]);
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+ && CONST_INT_P (operands[1]))
+ {
+ HOST_WIDE_INT val = INTVAL (operands[1]);
- if (((val & 0x80) && ! (val & 0xffffff00))
- || ((val & 0x800000) && ! (val & 0xff000000)))
- return \"movu %1,%0\";
- }
- return \"mov %1,%0\";
- case 2:
- case 3:
- return \"movbu %1,%0\";
- case 4:
- case 5:
- return \"fmov %1,%0\";
- default:
- gcc_unreachable ();
- }
-}"
+ if (((val & 0x80) && ! (val & 0xffffff00))
+ || ((val & 0x800000) && ! (val & 0xff000000)))
+ return \"movu %1,%0\";
+ }
+ return \"mov %1,%0\";
+ case 2:
+ case 3:
+ return \"movbu %1,%0\";
+ case 4:
+ case 5:
+ return \"fmov %1,%0\";
+ default:
+ gcc_unreachable ();
+ }
+ }"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 47) (const_int 25))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 47) (const_int 25))
+ ])
+ ]
)
(define_insn "*mn10300_movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m")
- (match_operand:QI 1 "general_operand" "0,I,i,i,da,m,d"))]
+ (match_operand:QI 1 "general_operand" "0, I,i,i, da, m,d"))]
"register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode)"
"*
@@ -118,15 +236,7 @@
case 2:
case 3:
case 4:
- if (CONST_DOUBLE_P (operands[1]))
- {
- rtx xoperands[2];
- xoperands[0] = operands[0];
- xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- output_asm_insn (\"mov %1,%0\", xoperands);
- return \"\";
- }
-
+ gcc_assert (! CONST_DOUBLE_P (operands[1]));
return \"mov %1,%0\";
case 5:
case 6:
@@ -135,12 +245,27 @@
gcc_unreachable ();
}
}"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 11)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ ])
+ ]
)
;; movhi
(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand")
+ [(set (match_operand:HI 0 "nonimmediate_operand")
(match_operand:HI 1 "general_operand"))]
""
"
@@ -152,8 +277,11 @@
}")
(define_insn "*am33_movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d*x*a*f,d*x*a,d*x*a,m,*f,d*x*a")
- (match_operand:HI 1 "general_operand" "0,d*x*ai,m,d*x*a,d*x*a*f,*f"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand"
+ ;; 0 1 2 3 4 5
+ "=d*x*a*f, d*x*a, d*x*a, m, *f, d*x*a")
+ (match_operand:HI 1 "general_operand"
+ "0, d*x*ai, m, d*x*a, d*x*a*f, *f"))]
"TARGET_AM33
&& (register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))"
@@ -164,14 +292,7 @@
case 0:
return \"nop\";
case 1:
- if (CONST_DOUBLE_P (operands[1]))
- {
- rtx xoperands[2];
- xoperands[0] = operands[0];
- xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- output_asm_insn (\"mov %1,%0\", xoperands);
- return \"\";
- }
+ gcc_assert (! CONST_DOUBLE_P (operands[1]));
if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
&& CONST_INT_P (operands[1]))
@@ -193,11 +314,25 @@
gcc_unreachable ();
}
}"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 47) (const_int 25))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 47) (const_int 25))
+ ])
+ ]
)
(define_insn "*mn10300_movhi"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m")
- (match_operand:HI 1 "general_operand" "0,I,i,i,da,m,d"))]
+ (match_operand:HI 1 "general_operand" "0, I,i,i, da, m,d"))]
"register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode)"
"*
@@ -210,14 +345,7 @@
case 2:
case 3:
case 4:
- if (CONST_DOUBLE_P (operands[1]))
- {
- rtx xoperands[2];
- xoperands[0] = operands[0];
- xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- output_asm_insn (\"mov %1,%0\", xoperands);
- return \"\";
- }
+ gcc_assert (! CONST_DOUBLE_P (operands[1]));
return \"mov %1,%0\";
case 5:
case 6:
@@ -226,6 +354,21 @@
gcc_unreachable ();
}
}"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 11)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ ])
+ ]
)
;; movsi and helpers
@@ -276,10 +419,13 @@
[(set (reg:SI PIC_REG)
(mem:SI (post_inc:SI (reg:SI SP_REG))))]
"reload_completed"
- "movm (sp),[a2]")
+ "movm (sp),[a2]"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 44) (const_int 33)))]
+)
(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand")
+ [(set (match_operand:SI 0 "nonimmediate_operand")
(match_operand:SI 1 "general_operand"))]
""
"
@@ -322,62 +468,49 @@
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand"
- "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,axR,!*y,*f,*f,dxaQ")
+ "=dax, dax, m, dax, axR, !*y")
(match_operand:SI 1 "general_operand"
- "0,0,I,I,dx,ax,dx,ax,dixm,aixm,dixm,aixm,!*y,axR,0,dxaQi*f,*f"))]
+ "0, Idax, dax, im, !*y, axR"))
+ ]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)"
"*
-{
- switch (which_alternative)
- {
- case 0:
- case 1:
+ {
+ if (which_alternative == 0)
return \"nop\";
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- case 13:
- if (CONST_DOUBLE_P (operands[1]))
- {
- rtx xoperands[2];
- xoperands[0] = operands[0];
- xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- output_asm_insn (\"mov %1,%0\", xoperands);
- return \"\";
- }
- if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
- && CONST_INT_P (operands[1]))
- {
- HOST_WIDE_INT val = INTVAL (operands[1]);
+ gcc_assert (! CONST_DOUBLE_P (operands[1]));
- if (((val & 0x80) && ! (val & 0xffffff00))
- || ((val & 0x800000) && ! (val & 0xff000000)))
- return \"movu %1,%0\";
- }
- return \"mov %1,%0\";
- case 14:
- return \"nop\";
- case 15:
- case 16:
- return \"fmov %1,%0\";
- default:
- gcc_unreachable ();
- }
-}"
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+ && CONST_INT_P (operands[1]))
+ {
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (((val & 0x80) && ! (val & 0xffffff00))
+ || ((val & 0x800000) && ! (val & 0xff000000)))
+ return \"movu %1, %0\";
+ }
+
+ return \"mov %1, %0\";
+ }"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ ])
+ ]
)
(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand")
+ [(set (match_operand:SF 0 "nonimmediate_operand")
(match_operand:SF 1 "general_operand"))]
""
"
@@ -389,44 +522,59 @@
}")
(define_insn "*movsf_internal"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,dx,ax,dx,a,f,dxaQ,daxm,dax")
- (match_operand:SF 1 "general_operand" "0,0,0,G,G,fdxaQF,f,dax,daxFm"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand"
+ ;; 0 1 2 3 4 5
+ "=fdxa, dxa, f, dxaQ, daxm, dax")
+ (match_operand:SF 1 "general_operand"
+ " 0, G, fdxaQF, f, dax, daxFm"))
+ ]
"register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)"
"*
-{
- switch (which_alternative)
- {
- case 0:
- case 1:
- case 2:
- return \"nop\";
- /* Cases 3 & 4: below. */
- case 5:
- case 6:
- return \"fmov %1, %0\";
- case 3:
- case 4:
- case 7:
- case 8:
- if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
- && CONST_INT_P (operands[1]))
- {
- HOST_WIDE_INT val = INTVAL (operands[1]);
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return \"nop\";
+ /* case 1: below. */
+ case 2:
+ case 3:
+ return \"fmov %1, %0\";
+ case 1:
+ case 4:
+ case 5:
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+ && CONST_INT_P (operands[1]))
+ {
+ HOST_WIDE_INT val = INTVAL (operands[1]);
- if (((val & 0x80) && ! (val & 0xffffff00))
- || ((val & 0x800000) && ! (val & 0xff000000)))
- return \"movu %1,%0\";
- }
- return \"mov %1,%0\";
- default:
- gcc_unreachable ();
- }
-}"
+ if (((val & 0x80) && ! (val & 0xffffff00))
+ || ((val & 0x800000) && ! (val & 0xff000000)))
+ return \"movu %1, %0\";
+ }
+ return \"mov %1, %0\";
+ default:
+ gcc_unreachable ();
+ }
+ }"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 47) (const_int 25))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 47) (const_int 25))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ ])
+ ]
)
(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand")
+ [(set (match_operand:DI 0 "nonimmediate_operand")
(match_operand:DI 1 "general_operand"))]
""
"
@@ -437,11 +585,10 @@
operands[1] = copy_to_mode_reg (DImode, operand1);
}")
-(define_insn "*movdi_internal"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,*f,*f,*f,dxa,*f,Q")
- (match_operand:DI 1 "general_operand"
- "0,0,I,I,dx,ax,dx,ax,dxim,axim,dxim,axim,0,*f,dxai,*f,Q,*f"))]
+
+(define_insn "*movdi_internal" ;; 0 1 2 3 4 5 6 7 8 9
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=dx,ax,dx,a,dxm,dxm,a, a,dx,a")
+ (match_operand:DI 1 "general_operand" "0,0, I, I,dx, a, dx,a,im,im"))]
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)"
"*
@@ -469,8 +616,6 @@
case 7:
case 8:
case 9:
- case 10:
- case 11:
if (CONST_INT_P (operands[1]))
{
rtx low, high;
@@ -568,34 +713,28 @@
output_asm_insn (\"mov %H1,%H0\", operands);
return \"\";
}
- case 12:
- return \"nop\";
- case 13:
- case 14:
- case 15:
- return \"fmov %L1, %L0\;fmov %H1, %H0\";
- case 16:
- if (MEM_P (operands[1])
- && CONST_INT_P (XEXP (operands[1], 0))
- && (INTVAL (XEXP (operands[1], 0)) & 7) == 0)
- return \"fmov %D1, %D0\";
- else
- return \"fmov %L1, %L0\;fmov %H1, %H0\";
- case 17:
- if (MEM_P (operands[0])
- && CONST_INT_P (XEXP (operands[0], 0))
- && (INTVAL (XEXP (operands[0], 0)) & 7) == 0)
- return \"fmov %D1, %D0\";
- else
- return \"fmov %L1, %L0\;fmov %H1, %H0\";
default:
gcc_unreachable ();
}
-}"
+ }"
+ ;; The timing of "37" is an approximation of the worst case sceanario.
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 11)
+ (const_int 22)
+ (const_int 22)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ ])
+ ]
)
(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand")
+ [(set (match_operand:DF 0 "nonimmediate_operand")
(match_operand:DF 1 "general_operand"))]
""
"
@@ -608,63 +747,52 @@
(define_insn "*am33_2_movdf"
[(set (match_operand:DF 0 "nonimmediate_operand"
- ;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- "=f,dx,ax,dx,f,f,dxa,f,Q,a,dxm,dxm,axm,axm,dx,dx,ax,ax")
+ ;; 0 1 2 3 4 5 6 7 8 9 10 11
+ "=fdax,dax,fdxa,f, f,Q,dxm,dxm,a, a,dx,a")
(match_operand:DF 1 "general_operand"
- ;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- "0,0,0,G,f,dxaF,f,Q,f,G,dx,ax,dx,ax,dxFm,axFm,dxFm,axFm"))]
+ " 0, G, f, dxaF,Q,f,dx, a, dx,a,Fm,Fm"))]
"TARGET_AM33_2
- && (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
+ && (register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode))"
"*
-{
- long val[2];
- REAL_VALUE_TYPE rv;
+ {
+ long val[2];
+ REAL_VALUE_TYPE rv;
- switch (which_alternative)
- {
+ switch (which_alternative)
+ {
case 0:
- case 1:
- case 2:
return \"nop\";
+ case 1:
+ return \"mov 0, %L0\; mov 0, %H0\";
+
+ case 2:
case 3:
- return \"mov 0, %L0\;mov 0, %H0\";
+ return \"fmov %L1, %L0\; fmov %H1, %H0\";
case 4:
- case 5:
- case 6:
- return \"fmov %L1, %L0\;fmov %H1, %H0\";
-
- case 7:
if (MEM_P (operands[1])
&& CONST_INT_P (XEXP (operands[1], 0))
&& (INTVAL (XEXP (operands[1], 0)) & 7) == 0)
return \"fmov %D1, %D0\";
else
- return \"fmov %L1, %L0\;fmov %H1, %H0\";
+ return \"fmov %L1, %L0\; fmov %H1, %H0\";
- case 8:
+ case 5:
if (MEM_P (operands[0])
&& CONST_INT_P (XEXP (operands[0], 0))
&& (INTVAL (XEXP (operands[0], 0)) & 7) == 0)
return \"fmov %D1, %D0\";
else
- return \"fmov %L1, %L0\;fmov %H1, %H0\";
+ return \"fmov %L1, %L0\; fmov %H1, %H0\";
+ case 6:
+ case 7:
+ case 8:
case 9:
- if (rtx_equal_p (operands[0], operands[1]))
- return \"sub %L1,%L0\;mov %L0,%H0\";
- else
- return \"mov %1,%L0\;mov %L0,%H0\";
case 10:
case 11:
- case 12:
- case 13:
- case 14:
- case 15:
- case 16:
- case 17:
if (CONST_INT_P (operands[1]))
{
rtx low, high;
@@ -699,9 +827,9 @@
if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)),
XEXP (operands[1], 0)))
- return \"mov %H1,%H0\;mov %L1,%L0\";
+ return \"mov %H1, %H0\; mov %L1, %L0\";
else
- return \"mov %L1,%L0\;mov %H1,%H0\";
+ return \"mov %L1, %L0\; mov %H1, %H0\";
}
else if (MEM_P (operands[1])
@@ -713,7 +841,7 @@
xoperands[0] = operands[0];
xoperands[1] = XEXP (operands[1], 0);
- output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\",
+ output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\",
xoperands);
return \"\";
}
@@ -734,9 +862,9 @@
== EXTENDED_REGS)
&& (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
|| ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
- output_asm_insn (\"movu %L1,%L0\", operands);
+ output_asm_insn (\"movu %L1, %L0\", operands);
else
- output_asm_insn (\"mov %L1,%L0\", operands);
+ output_asm_insn (\"mov %L1, %L0\", operands);
if ((CONST_INT_P (operands[1])
|| CONST_DOUBLE_P (operands[1]))
@@ -745,7 +873,7 @@
if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"mov 0, %H0\", operands);
else
- output_asm_insn (\"mov %H1,%H0\", operands);
+ output_asm_insn (\"mov %H1, %H0\", operands);
}
else if ((CONST_INT_P (operands[1])
|| CONST_DOUBLE_P (operands[1]))
@@ -757,52 +885,60 @@
== EXTENDED_REGS)
&& (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
|| ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
- output_asm_insn (\"movu %H1,%H0\", operands);
+ output_asm_insn (\"movu %H1, %H0\", operands);
else
- output_asm_insn (\"mov %H1,%H0\", operands);
+ output_asm_insn (\"mov %H1, %H0\", operands);
return \"\";
}
default:
gcc_unreachable ();
}
-}"
+ }"
+ ;; The timing of "37" is an approximation of the worst case sceanario.
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 22)
+ (const_int 22)
+ (const_int 22)
+ (const_int 22)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ ])
+ ]
)
(define_insn "*mn10300_movdf"
[(set (match_operand:DF 0 "nonimmediate_operand"
- ;; 0 1 2 3 4 5 6 7 8 9 10
- "=dxa,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax")
+ ;;0 1 2 3 4 5 6 7
+ "=dxa, dax, dxm, dxm, a, a, dx, a")
(match_operand:DF 1 "general_operand"
- ;; 0 1 2 3 4 5 6 7 8 9 10
- "0,G,G,dx,ax,dx,ax,dxFm,axFm,dxFm,axFm"))]
+ " 0, G, dx, a, dx, a, Fm, Fm"))]
"register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode)"
"*
-{
- long val[2];
- REAL_VALUE_TYPE rv;
+ {
+ long val[2];
+ REAL_VALUE_TYPE rv;
- switch (which_alternative)
- {
+ switch (which_alternative)
+ {
case 0:
return \"nop\";
case 1:
- return \"mov 0, %L0\;mov 0, %H0\";
+ return \"mov 0, %L0\; mov 0, %H0\";
case 2:
- if (rtx_equal_p (operands[0], operands[1]))
- return \"sub %L1,%L0\;mov %L0,%H0\";
- else
- return \"mov %1,%L0\;mov %L0,%H0\";
case 3:
case 4:
case 5:
case 6:
case 7:
- case 8:
- case 9:
- case 10:
if (CONST_INT_P (operands[1]))
{
rtx low, high;
@@ -810,7 +946,7 @@
val[0] = INTVAL (low);
val[1] = INTVAL (high);
}
- if (CONST_DOUBLE_P (operands[1]))
+ if (CONST_DOUBLE_P (operands[1]))
{
if (GET_MODE (operands[1]) == DFmode)
{
@@ -837,10 +973,9 @@
if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)),
XEXP (operands[1], 0)))
- return \"mov %H1,%H0\;mov %L1,%L0\";
+ return \"mov %H1, %H0\; mov %L1, %L0\";
else
- return \"mov %L1,%L0\;mov %H1,%H0\";
-
+ return \"mov %L1, %L0\; mov %H1, %H0\";
}
else if (MEM_P (operands[1])
&& CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
@@ -851,7 +986,7 @@
xoperands[0] = operands[0];
xoperands[1] = XEXP (operands[1], 0);
- output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\",
+ output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\",
xoperands);
return \"\";
}
@@ -864,7 +999,7 @@
if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"mov 0, %L0\", operands);
else
- output_asm_insn (\"mov %L1,%L0\", operands);
+ output_asm_insn (\"mov %L1, %L0\", operands);
}
else if ((CONST_INT_P (operands[1])
|| CONST_DOUBLE_P (operands[1]))
@@ -872,9 +1007,9 @@
== EXTENDED_REGS)
&& (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
|| ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
- output_asm_insn (\"movu %L1,%L0\", operands);
+ output_asm_insn (\"movu %L1, %L0\", operands);
else
- output_asm_insn (\"mov %L1,%L0\", operands);
+ output_asm_insn (\"mov %L1, %L0\", operands);
if ((CONST_INT_P (operands[1])
|| CONST_DOUBLE_P (operands[1]))
@@ -883,29 +1018,40 @@
if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"mov 0, %H0\", operands);
else
- output_asm_insn (\"mov %H1,%H0\", operands);
+ output_asm_insn (\"mov %H1, %H0\", operands);
}
else if ((CONST_INT_P (operands[1])
|| CONST_DOUBLE_P (operands[1]))
&& val[0] == val[1])
- output_asm_insn (\"mov %L0,%H0\", operands);
+ output_asm_insn (\"mov %L0, %H0\", operands);
else if ((CONST_INT_P (operands[1])
|| CONST_DOUBLE_P (operands[1]))
&& (REGNO_REG_CLASS (true_regnum (operands[0]))
== EXTENDED_REGS)
&& (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
|| ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
- output_asm_insn (\"movu %H1,%H0\", operands);
+ output_asm_insn (\"movu %H1, %H0\", operands);
else
- output_asm_insn (\"mov %H1,%H0\", operands);
+ output_asm_insn (\"mov %H1, %H0\", operands);
return \"\";
}
default:
gcc_unreachable ();
}
-}"
+ }"
+ ;; Timings of "37" is approximation of the worst case sceanario.
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 22)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ (const_int 37)
+ ])
+ ]
)
-
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
@@ -1000,7 +1146,8 @@
default:
gcc_unreachable ();
}
-}"
+ }"
+ [(set_attr "timings" "11,11,11,11,11,11,22")]
)
(define_insn "*mn10300_addsi3"
@@ -1045,6 +1192,7 @@
gcc_unreachable ();
}
}"
+ [(set_attr "timings" "11,11,11,11,11,22")]
)
;; ----------------------------------------------------------------------
@@ -1062,33 +1210,36 @@
"")
(define_insn "*am33_subsi3"
- [(set (match_operand:SI 0 "register_operand" "=dax,!dax")
+ [(set (match_operand:SI 0 "register_operand" "=dax,!dax")
(minus:SI (match_operand:SI 1 "register_operand" "0,dax")
- (match_operand:SI 2 "nonmemory_operand" "daxi,dax")))]
+ (match_operand:SI 2 "nonmemory_operand" "daxi,dax")))
+ (clobber (reg:CC CC_REG))
+ ]
"TARGET_AM33"
"*
-{
- if (true_regnum (operands[0]) == true_regnum (operands[1]))
- return \"sub %2,%0\";
- else
- {
- enum reg_class src1_class, src2_class, dst_class;
-
- src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
- src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
- dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
-
- /* If no extended registers are used, then the best way to handle
- this is to copy the first source operand into the destination
- and emit a two address subtraction. */
- if (src1_class != EXTENDED_REGS
- && src2_class != EXTENDED_REGS
- && dst_class != EXTENDED_REGS
- && true_regnum (operands[0]) != true_regnum (operands[2]))
- return \"mov %1,%0\;sub %2,%0\";
- return \"sub %2,%1,%0\";
- }
-}"
+ {
+ if (true_regnum (operands[0]) == true_regnum (operands[1]))
+ return \"sub %2,%0\";
+ else
+ {
+ enum reg_class src1_class, src2_class, dst_class;
+
+ src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
+ src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
+ dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
+
+ /* If no extended registers are used, then the best way to handle
+ this is to copy the first source operand into the destination
+ and emit a two address subtraction. */
+ if (src1_class != EXTENDED_REGS
+ && src2_class != EXTENDED_REGS
+ && dst_class != EXTENDED_REGS
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"mov %1,%0\;sub %2,%0\";
+ return \"sub %2,%1,%0\";
+ }
+ }"
+ [(set_attr "timings" "11,22")]
)
(define_insn "*mn10300_subsi3"
@@ -1099,6 +1250,8 @@
]
""
"sub %2,%0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22)))]
)
(define_expand "negsi2"
@@ -1127,16 +1280,20 @@
]
"TARGET_AM33"
"mul %1,%2,%H0,%L0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 24) (const_int 23)))]
)
(define_insn "umulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=dax")
+ [(set (match_operand:DI 0 "register_operand" "=dax")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "dax"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "dax"))))
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
"mulu %1,%2,%H0,%L0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 24) (const_int 23)))]
)
(define_expand "mulsi3"
@@ -1163,6 +1320,7 @@
else
return \"mul %2,%0\";
}"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") (const_int 24) (const_int 23)))]
)
(define_insn "*mn10300_mulsi3"
@@ -1179,13 +1337,15 @@
else
return \"mul %2,%0\";
}"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 24) (const_int 23)))]
)
(define_expand "udivmodsi4"
- [(parallel [(set (match_operand:SI 0 "nonimmediate_operand")
+ [(parallel [(set (match_operand:SI 0 "register_operand")
(udiv:SI (match_operand:SI 1 "general_operand")
(match_operand:SI 2 "general_operand")))
- (set (match_operand:SI 3 "nonimmediate_operand")
+ (set (match_operand:SI 3 "register_operand")
(umod:SI (match_dup 1) (match_dup 2)))
(clobber (reg:CC CC_REG))
])
@@ -1199,11 +1359,11 @@
}"
)
-(define_insn "*udivmodsi4_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx")
+(define_insn "*udivmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=dx")
(udiv:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "register_operand" "dx")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=&d")
+ (set (match_operand:SI 3 "register_operand" "=&d")
(umod:SI (match_dup 1) (match_dup 2)))
(clobber (reg:CC CC_REG))
]
@@ -1217,13 +1377,22 @@
else
return \"divu %2,%0\;mov mdr,%3\";
}"
+ ;; Timings: AM33 AM34
+ ;; SUB 1/1 1/1
+ ;; MOV 1/1 1/1
+ ;; DIVU 38/39 42/43
+ ;; MOV 1/1 1/1
+ ;; --------------------
+ ;; total 41/42 45/46 (worst case sceanario)
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 4546) (const_int 4142)))]
)
(define_insn "divmodsi4"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx")
- (div:SI (match_operand:SI 1 "general_operand" "0")
- (match_operand:SI 2 "general_operand" "dx")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=dx")
+ (div:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "dx")))
+ (set (match_operand:SI 3 "register_operand" "=d")
(mod:SI (match_dup 1) (match_dup 2)))
(clobber (reg:CC CC_REG))
]
@@ -1235,6 +1404,13 @@
else
return \"ext %0\;div %2,%0\;mov mdr,%3\";
}"
+ ;; Timings: AM33 AM34
+ ;; EXT 1/1 1/1
+ ;; DIV 38/39 42/43
+ ;; --------------------
+ ;; total 39/40 43/44 (worst case sceanario)
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 4344) (const_int 3940)))]
)
@@ -1259,44 +1435,40 @@
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
- "*
-{
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xff)
- return \"extbu %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xffff)
- return \"exthu %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0x7fffffff)
- return \"add %0,%0\;lsr 1,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0x3fffffff)
- return \"asl2 %0\;lsr 2,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0x1fffffff)
- return \"add %0,%0\;asl2 %0\;lsr 3,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0x0fffffff)
- return \"asl2 %0\;asl2 %0\;lsr 4,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xfffffffe)
- return \"lsr 1,%0\;add %0,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xfffffffc)
- return \"lsr 2,%0\;asl2 %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xfffffff8)
- return \"lsr 3,%0\;add %0,%0\;asl2 %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xfffffff0)
- return \"lsr 4,%0\;asl2 %0\;asl2 %0\";
- if (REG_P (operands[2]) && REG_P (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[2])
- && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
- return \"mov %1,%0\;and %2,%0\";
- if (REG_P (operands[2]) && REG_P (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[2]))
- return \"and %1,%2,%0\";
- if (REG_P (operands[2]) && REG_P (operands[0])
- && true_regnum (operands[2]) == true_regnum (operands[0]))
- return \"and %1,%0\";
- return \"and %2,%0\";
-}"
+ {
+ if (CONST_INT_P (operands[2]))
+ switch (INTVAL (operands[2]))
+ {
+ case 0xff: return "extbu %0";
+ case 0xffff: return "exthu %0";
+ case 0x7fffffff: return "add %0, %0; lsr 1, %0";
+ case 0x3fffffff: return "asl2 %0; lsr 2, %0";
+ case 0x1fffffff: return "add %0, %0; asl2 %0; lsr 3, %0";
+ case 0x0fffffff: return "asl2 %0; asl2 %0; lsr 4, %0";
+ case 0xfffffffe: return "lsr 1, %0; add %0, %0";
+ case 0xfffffffc: return "lsr 2, %0; asl2 %0";
+ case 0xfffffff8: return "lsr 3, %0; add %0, %0; asl2 %0";
+ case 0xfffffff0: return "lsr 4, %0; asl2 %0; asl2 %0";
+ }
+
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2])
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+ return "mov %1, %0; and %2, %0";
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return "and %1, %2, %0";
+ if (REG_P (operands[2]) && REG_P (operands[0])
+ && true_regnum (operands[2]) == true_regnum (operands[0]))
+ return "and %1, %0";
+
+ return "and %2, %0";
+ }
+ [(set_attr "timings" "33")]
)
(define_insn "*mn10300_andsi3"
@@ -1306,30 +1478,25 @@
(clobber (reg:CC CC_REG))
]
""
- "*
-{
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xff)
- return \"extbu %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xffff)
- return \"exthu %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0x7fffffff)
- return \"add %0,%0\;lsr 1,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0x3fffffff)
- return \"asl2 %0\;lsr 2,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0x1fffffff)
- return \"add %0,%0\;asl2 %0\;lsr 3,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0x0fffffff)
- return \"asl2 %0\;asl2 %0\;lsr 4,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xfffffffe)
- return \"lsr 1,%0\;add %0,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xfffffffc)
- return \"lsr 2,%0\;asl2 %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xfffffff8)
- return \"lsr 3,%0\;add %0,%0\;asl2 %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 0xfffffff0)
- return \"lsr 4,%0\;asl2 %0\;asl2 %0\";
- return \"and %2,%0\";
-}"
+ {
+ if (CONST_INT_P (operands[2]))
+ switch (INTVAL (operands[2]))
+ {
+ case 0xff: return "extbu %0";
+ case 0xffff: return "exthu %0";
+ case 0x7fffffff: return "add %0, %0; lsr 1, %0";
+ case 0x3fffffff: return "asl2 %0; lsr 2, %0";
+ case 0x1fffffff: return "add %0, %0; asl2 %0; lsr 3, %0";
+ case 0x0fffffff: return "asl2 %0; asl2 %0; lsr 4, %0";
+ case 0xfffffffe: return "lsr 1, %0; add %0, %0";
+ case 0xfffffffc: return "lsr 2, %0; asl2 %0";
+ case 0xfffffff8: return "lsr 3, %0; add %0, %0; asl2 %0";
+ case 0xfffffff0: return "lsr 4, %0; asl2 %0; asl2 %0";
+ }
+
+ return "and %2, %0";
+ }
+ [(set_attr "timings" "33")]
)
;; ----------------------------------------------------------------------
@@ -1354,33 +1521,35 @@
]
"TARGET_AM33"
"*
-{
- if (REG_P (operands[2]) && REG_P (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[2])
- && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
- return \"mov %1,%0\;or %2,%0\";
- if (REG_P (operands[2]) && REG_P (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[2]))
- return \"or %1,%2,%0\";
- if (REG_P (operands[2]) && REG_P (operands[0])
- && true_regnum (operands[2]) == true_regnum (operands[0]))
- return \"or %1,%0\";
- return \"or %2,%0\";
-}"
+ {
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2])
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+ return \"mov %1,%0\;or %2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"or %1,%2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[0])
+ && true_regnum (operands[2]) == true_regnum (operands[0]))
+ return \"or %1,%0\";
+ return \"or %2,%0\";
+ }"
+ [(set_attr "timings" "22")]
)
(define_insn "*mn10300_iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=dx")
+ [(set (match_operand:SI 0 "register_operand" "=dx")
(ior:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "dxi")))
(clobber (reg:CC CC_REG))
]
""
"or %2,%0"
+ [(set_attr "timings" "33")]
)
;; ----------------------------------------------------------------------
@@ -1398,40 +1567,42 @@
"")
(define_insn "*am33_xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+ [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
(xor:SI (match_operand:SI 1 "register_operand" "%0,dax")
(match_operand:SI 2 "nonmemory_operand" "dxi,dax")))
(clobber (reg:CC CC_REG))
]
"TARGET_AM33"
"*
-{
- if (REG_P (operands[2]) && REG_P (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[2])
- && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
- return \"mov %1,%0\;xor %2,%0\";
- if (REG_P (operands[2]) && REG_P (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[1])
- && true_regnum (operands[0]) != true_regnum (operands[2]))
- return \"xor %1,%2,%0\";
- if (REG_P (operands[2]) && REG_P (operands[0])
- && true_regnum (operands[2]) == true_regnum (operands[0]))
- return \"xor %1,%0\";
- return \"xor %2,%0\";
-}"
+ {
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2])
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+ return \"mov %1,%0\;xor %2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"xor %1,%2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[0])
+ && true_regnum (operands[2]) == true_regnum (operands[0]))
+ return \"xor %1,%0\";
+ return \"xor %2,%0\";
+ }"
+ [(set_attr "timings" "22")]
)
(define_insn "*mn10300_xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=dx")
+ [(set (match_operand:SI 0 "register_operand" "=dx")
(xor:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "dxi")))
(clobber (reg:CC CC_REG))
]
""
"xor %2,%0"
+ [(set_attr "timings" "11")]
)
;; ----------------------------------------------------------------------
@@ -1484,17 +1655,29 @@
"@
bclr 255,%A0
clr %0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 66) (const_int 77))
+ (const_int 11)
+ ])
+ ]
)
(define_insn "*byte_set"
[(set (match_operand:QI 0 "nonimmediate_operand" "=R,d") (const_int -1))
(clobber (reg:CC CC_REG))
]
- "( ! MEM_P (operands[0])) || (! MEM_VOLATILE_P (operands[0])
- && GET_CODE (XEXP (operands[0], 0)) != PLUS)"
+ "(! MEM_P (operands[0])) || (! MEM_VOLATILE_P (operands[0])
+ && GET_CODE (XEXP (operands[0], 0)) != PLUS)"
"@
bset 255,%A0
mov -1,%0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 66) (const_int 77))
+ (const_int 11)
+ ])
+ ]
)
(define_insn "*bit_clear1"
@@ -1508,6 +1691,12 @@
"@
bclr %N1,%A0
and %1,%0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 66) (const_int 77))
+ (const_int 11)
+ ])
+ ]
)
(define_insn "*bit_clear2"
@@ -1521,6 +1710,12 @@
"@
bclr %U1,%A0
bclr %1,%0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 66) (const_int 77))
+ (const_int 66)
+ ])
+ ]
)
(define_insn "*bit_set"
@@ -1534,6 +1729,12 @@
"@
bset %U1,%A0
or %1,%0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 66) (const_int 77))
+ (const_int 11)
+ ])
+ ]
)
(define_expand "iorqi3"
@@ -1547,12 +1748,12 @@
"")
(define_insn "*am33_iorqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=R,T,r")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=R,T,r")
(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
;; This constraint should really be nonmemory_operand,
;; but making it general_operand, along with the
- ;; condition that not both input operands are MEMs, it
- ;; here helps combine do a better job.
+ ;; condition that not both input operands are MEMs,
+ ;; helps combine do a better job.
(match_operand:QI 2 "general_operand" "i,d,ir")))
(clobber (reg:CC CC_REG))
]
@@ -1562,15 +1763,22 @@
bset %U2,%A0
bset %2,%0
or %2,%0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 66) (const_int 77))
+ (const_int 66)
+ (const_int 11)
+ ])
+ ]
)
(define_insn "*mn10300_iorqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=R,T,d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=R,T,d")
(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
;; This constraint should really be nonmemory_operand,
;; but making it general_operand, along with the
- ;; condition that not both input operands are MEMs, it
- ;; here helps combine do a better job.
+ ;; condition that not both input operands are MEMs,
+ ;; helps combine do a better job.
(match_operand:QI 2 "general_operand" "i,d,id")))
(clobber (reg:CC CC_REG))
]
@@ -1579,6 +1787,13 @@
bset %U2,%A0
bset %2,%0
or %2,%0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 66) (const_int 77))
+ (const_int 66)
+ (const_int 11)
+ ])
+ ]
)
(define_insn "*test_int_bitfield"
@@ -1611,7 +1826,7 @@
(define_insn "*test_byte_bitfield"
[(set (reg:CC CC_REG)
- (compare (zero_extract:SI (match_operand:QI 0 "general_operand" "R,dx")
+ (compare (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "R,dx")
(match_operand 1 "const_int_operand" "")
(match_operand 2 "const_int_operand" ""))
(const_int 0)))]
@@ -1653,6 +1868,13 @@
output_asm_insn (\"btst %U1,%A0\", xoperands);
return \"\";
}"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 44) (const_int 55))
+ ])
+ ]
)
(define_insn "*bit_test"
@@ -1663,18 +1885,27 @@
]
""
"btst %1,%0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22)))]
)
(define_insn "*subreg_bit_test"
[(set (reg:CC CC_REG)
(compare (and:SI
- (subreg:SI (match_operand:QI 0 "general_operand" "R,dx") 0)
+ (subreg:SI (match_operand:QI 0 "nonimmediate_operand" "R,dx") 0)
(match_operand:SI 1 "const_8bit_operand" ""))
(const_int 0)))]
""
"@
btst %U1,%A0
btst %1,%0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 44) (const_int 55))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ ])
+ ]
)
@@ -1750,11 +1981,19 @@
return mn10300_output_cmp (operands[0], insn);
return \"cmp %1,%0\";
}
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22))
+ (const_int 22)
+ ])
+ ]
)
(define_insn "integer_conditional_branch"
[(set (pc)
- (if_then_else (match_operator 0 "comparison_operator" [(reg:CC CC_REG) (const_int 0)])
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(reg:CC CC_REG) (const_int 0)])
(label_ref (match_operand 1 "" ""))
(pc)))]
""
@@ -1805,6 +2044,8 @@
(match_operand:SF 1 "nonmemory_operand" "fF")))]
"TARGET_AM33_2"
"fcmp %1, %0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 25)))]
)
(define_insn "float_conditional_branch"
@@ -1815,6 +2056,8 @@
(pc)))]
"TARGET_AM33_2"
"fb%b0 %1"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 44) (const_int 33)))]
)
;; Unconditional and other jump instructions.
@@ -1824,12 +2067,16 @@
(label_ref (match_operand 0 "" "")))]
""
"jmp %l0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 44)))]
)
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "a"))]
""
"jmp (%0)"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 33)))]
)
(define_expand "builtin_setjmp_receiver"
@@ -1876,6 +2123,8 @@
(use (label_ref (match_operand 1 "" "")))]
""
"jmp (%0)"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 33)))]
)
;; Call subroutine with no return value.
@@ -1909,16 +2158,19 @@
;; NB: Mode on match_operand 0 deliberately omitted in
;; order to be able to match UNSPECs in PIC mode.
(define_insn "call_internal"
- [(call (mem:QI (match_operand 0 "call_address_operand" "aS"))
- (match_operand:SI 1 "general_operand" "g"))]
+ [(call (mem:QI (match_operand 0 "call_address_operand" "a,S"))
+ (match_operand:SI 1 "general_operand" "g,g"))]
""
- "*
-{
- if (REG_P (operands[0]))
- return \"calls %C0\";
- else
- return \"call %C0,[],0\";
-}"
+ "@
+ calls %C0
+ call %C0,[],0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 33) (const_int 44))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 55) (const_int 33))
+ ])
+ ]
)
;; Call subroutine, returning value in operand 0
@@ -1956,17 +2208,20 @@
;; NB: Mode on match_operands 0 and 1 deliberately omitted
;; in order to be able to match UNSPECs in PIC mode.
(define_insn "call_value_internal"
- [(set (match_operand 0 "register_operand" "=dax")
- (call (mem:QI (match_operand 1 "call_address_operand" "aS"))
- (match_operand:SI 2 "general_operand" "g")))]
+ [(set (match_operand 0 "register_operand" "=dax,dax")
+ (call (mem:QI (match_operand 1 "call_address_operand" "a,S"))
+ (match_operand:SI 2 "general_operand" "g,g")))]
""
- "*
-{
- if (REG_P (operands[1]))
- return \"calls %C1\";
- else
- return \"call %C1,[],0\";
-}"
+ "@
+ calls %C1
+ call %C1,[],0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 33) (const_int 44))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 55) (const_int 33))
+ ])
+ ]
)
(define_expand "untyped_call"
@@ -2000,16 +2255,16 @@
;; ----------------------------------------------------------------------
(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "general_operand")
+ [(set (match_operand:SI 0 "register_operand")
(zero_extend:SI
- (match_operand:QI 1 "general_operand")))]
+ (match_operand:QI 1 "nonimmediate_operand")))]
""
"")
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx,dx,dx,!dax,!dax,!dax")
+(define_insn "*zero_extendqisi2_am33"
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx,dx,!dax,!dax,!dax")
(zero_extend:SI
- (match_operand:QI 1 "general_operand" "0,dax,m,0,dax,m")))]
+ (match_operand:QI 1 "nonimmediate_operand" "0,dax,m,0,dax,m")))]
"TARGET_AM33"
"@
extbu %0
@@ -2018,30 +2273,48 @@
extbu %0
mov %1,%0\;extbu %0
movbu %1,%0"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 22)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (const_int 11)
+ (const_int 22)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ ])
+ ]
)
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx,dx,dx")
+(define_insn "*zero_extendqisi2_mn10300"
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx,dx")
(zero_extend:SI
- (match_operand:QI 1 "general_operand" "0,d,m")))]
+ (match_operand:QI 1 "nonimmediate_operand" "0,d,m")))]
""
"@
extbu %0
mov %1,%0\;extbu %0
movbu %1,%0"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 22)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ ])
+ ]
)
(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "general_operand")
+ [(set (match_operand:SI 0 "register_operand")
(zero_extend:SI
- (match_operand:HI 1 "general_operand")))]
+ (match_operand:HI 1 "nonimmediate_operand")))]
""
"")
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx,dx,dx,!dax,!dax,!dax")
+(define_insn "*zero_extendhisi2_am33"
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx,dx,!dax,!dax,!dax")
(zero_extend:SI
- (match_operand:HI 1 "general_operand" "0,dax,m,0,dax,m")))]
+ (match_operand:HI 1 "nonimmediate_operand" "0,dax,m,0,dax,m")))]
"TARGET_AM33"
"@
exthu %0
@@ -2050,77 +2323,99 @@
exthu %0
mov %1,%0\;exthu %0
movhu %1,%0"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 22)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ (const_int 11)
+ (const_int 22)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ ])
+ ]
)
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx,dx,dx")
+(define_insn "*zero_extendhisi2_mn10300"
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx,dx")
(zero_extend:SI
- (match_operand:HI 1 "general_operand" "0,dx,m")))]
+ (match_operand:HI 1 "nonimmediate_operand" "0,dx,m")))]
""
"@
exthu %0
mov %1,%0\;exthu %0
movhu %1,%0"
+ [(set_attr_alternative "timings"
+ [(const_int 11)
+ (const_int 22)
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 13) (const_int 24))
+ ])
+ ]
)
;;- sign extension instructions
(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "general_operand")
+ [(set (match_operand:SI 0 "register_operand")
(sign_extend:SI
- (match_operand:QI 1 "general_operand")))]
+ (match_operand:QI 1 "register_operand")))]
""
"")
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx,dx,!dax,!dax")
+(define_insn "*extendqisi2_am33"
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax,!dax")
(sign_extend:SI
- (match_operand:QI 1 "general_operand" "0,dx,0,dax")))]
+ (match_operand:QI 1 "register_operand" "0,dx,0,dax")))]
"TARGET_AM33"
"@
extb %0
mov %1,%0\;extb %0
extb %0
mov %1,%0\;extb %0"
+ [(set_attr "timings" "11,22,11,22")]
)
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx,dx")
+(define_insn "*extendqisi2_mn10300"
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx")
(sign_extend:SI
- (match_operand:QI 1 "general_operand" "0,dx")))]
+ (match_operand:QI 1 "register_operand" "0,dx")))]
""
"@
extb %0
mov %1,%0\;extb %0"
+ [(set_attr "timings" "11,22")]
)
(define_expand "extendhisi2"
- [(set (match_operand:SI 0 "general_operand")
+ [(set (match_operand:SI 0 "register_operand")
(sign_extend:SI
- (match_operand:HI 1 "general_operand")))]
+ (match_operand:HI 1 "register_operand")))]
""
"")
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx,dx,!dax,!dax")
+(define_insn "*extendhisi2_am33"
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax,!dax")
(sign_extend:SI
- (match_operand:HI 1 "general_operand" "0,dax,0,dax")))]
+ (match_operand:HI 1 "register_operand" "0,dax,0,dax")))]
"TARGET_AM33"
"@
exth %0
mov %1,%0\;exth %0
exth %0
mov %1,%0\;exth %0"
+ [(set_attr "timings" "11,22,11,22")]
)
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=dx,dx")
+(define_insn "*extendhisi2_mn10300"
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx")
(sign_extend:SI
- (match_operand:HI 1 "general_operand" "0,dx")))]
+ (match_operand:HI 1 "register_operand" "0,dx")))]
""
"@
exth %0
mov %1,%0\;exth %0"
+ [(set_attr "timings" "11,22")]
)
;; ----------------------------------------------------------------------
@@ -2147,30 +2442,31 @@
]
"TARGET_AM33"
"*
-{
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
- return \"add %0,%0\";
+ {
+ if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
+ return \"add %0,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 2)
- return \"asl2 %0\";
+ if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 2)
+ return \"asl2 %0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 3
- && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
- return \"asl2 %0\;add %0,%0\";
+ if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 3
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
+ return \"asl2 %0\;add %0,%0\";
- if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 4
- && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
- return \"asl2 %0\;asl2 %0\";
+ if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 4
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
+ return \"asl2 %0\;asl2 %0\";
- if (true_regnum (operands[1]) == true_regnum (operands[0]))
- return \"asl %S2,%0\";
+ if (true_regnum (operands[1]) == true_regnum (operands[0]))
+ return \"asl %S2,%0\";
- if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
- && true_regnum (operands[0]) != true_regnum (operands[2]))
- return \"mov %1,%0\;asl %S2,%0\";
- return \"asl %2,%1,%0\";
-}"
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"mov %1,%0\;asl %S2,%0\";
+ return \"asl %2,%1,%0\";
+ }"
+ [(set_attr "timings" "22")]
)
(define_insn "*mn10300_ashlsi3"
@@ -2187,6 +2483,7 @@
asl2 %0\;add %0,%0
asl2 %0\;asl2 %0
asl %S2,%0"
+ [(set_attr "timings" "11,11,22,22,11")]
)
(define_expand "lshrsi3"
@@ -2209,16 +2506,17 @@
]
"TARGET_AM33"
"*
-{
- if (true_regnum (operands[1]) == true_regnum (operands[0]))
- return \"lsr %S2,%0\";
-
- if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
- && true_regnum (operands[0]) != true_regnum (operands[2]))
- return \"mov %1,%0\;lsr %S2,%0\";
- return \"lsr %2,%1,%0\";
-}"
+ {
+ if (true_regnum (operands[1]) == true_regnum (operands[0]))
+ return \"lsr %S2,%0\";
+
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"mov %1,%0\;lsr %S2,%0\";
+ return \"lsr %2,%1,%0\";
+ }"
+ [(set_attr "timings" "22")]
)
(define_insn "*mn10300_lshrsi3"
@@ -2230,6 +2528,8 @@
]
""
"lsr %S2,%0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22)))]
)
(define_expand "ashrsi3"
@@ -2252,16 +2552,17 @@
]
"TARGET_AM33"
"*
-{
- if (true_regnum (operands[1]) == true_regnum (operands[0]))
- return \"asr %S2,%0\";
-
- if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
- && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
- && true_regnum (operands[0]) != true_regnum (operands[2]))
- return \"mov %1,%0\;asr %S2,%0\";
- return \"asr %2,%1,%0\";
-}"
+ {
+ if (true_regnum (operands[1]) == true_regnum (operands[0]))
+ return \"asr %S2,%0\";
+
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"mov %1,%0\;asr %S2,%0\";
+ return \"asr %2,%1,%0\";
+ }"
+ [(set_attr "timings" "22")]
)
(define_insn "*mn10300_ashrsi3"
@@ -2273,6 +2574,8 @@
]
""
"asr %S2,%0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 11) (const_int 22)))]
)
;; ----------------------------------------------------------------------
@@ -2352,6 +2655,8 @@
"@
fabs %0
fabs %1, %0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 14)))]
)
(define_expand "negdf2"
@@ -2421,6 +2726,8 @@
"@
fneg %0
fneg %1, %0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 14)))]
)
(define_expand "sqrtsf2"
@@ -2431,13 +2738,13 @@
]
"TARGET_AM33_2 && flag_unsafe_math_optimizations"
"
-{
- rtx scratch = gen_reg_rtx (SFmode);
- emit_insn (gen_rsqrtsf2 (scratch, operands[1], CONST1_RTX (SFmode)));
- emit_insn (gen_divsf3 (operands[0], force_reg (SFmode, CONST1_RTX (SFmode)),
- scratch));
- DONE;
-}")
+ {
+ rtx scratch = gen_reg_rtx (SFmode);
+ emit_insn (gen_rsqrtsf2 (scratch, operands[1], CONST1_RTX (SFmode)));
+ emit_insn (gen_divsf3 (operands[0], force_reg (SFmode, CONST1_RTX (SFmode)),
+ scratch));
+ DONE;
+ }")
(define_insn "rsqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f,f")
@@ -2449,6 +2756,8 @@
"@
frsqrt %0
frsqrt %1, %0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 4753) (const_int 2327)))]
)
(define_expand "addsf3"
@@ -2471,6 +2780,13 @@
"@
fadd %2, %0
fadd %2, %1, %0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 14))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 25))
+ ])
+ ]
)
(define_expand "subsf3"
@@ -2493,6 +2809,13 @@
"@
fsub %2, %0
fsub %2, %1, %0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 14))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 25))
+ ])
+ ]
)
(define_expand "mulsf3"
@@ -2515,6 +2838,13 @@
"@
fmul %2, %0
fmul %2, %1, %0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 14))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 25))
+ ])
+ ]
)
(define_insn "divsf3"
@@ -2527,6 +2857,13 @@
"@
fdiv %2, %0
fdiv %2, %1, %0"
+ [(set_attr_alternative "timings"
+ [(if_then_else (eq_attr "cpu" "am34")
+ (const_int 2531) (const_int 1216))
+ (if_then_else (eq_attr "cpu" "am34")
+ (const_int 2531) (const_int 1317))
+ ])
+ ]
)
(define_insn "fmaddsf4"
@@ -2538,6 +2875,8 @@
]
"TARGET_AM33_2"
"fmadd %1, %2, %3, %0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 24)))]
)
(define_insn "fmsubsf4"
@@ -2549,6 +2888,8 @@
]
"TARGET_AM33_2"
"fmsub %1, %2, %3, %0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 24)))]
)
(define_insn "fnmaddsf4"
@@ -2560,6 +2901,8 @@
]
"TARGET_AM33_2"
"fnmadd %1, %2, %3, %0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 24)))]
)
(define_insn "fnmsubsf4"
@@ -2571,6 +2914,8 @@
]
"TARGET_AM33_2"
"fnmsub %1, %2, %3, %0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 17) (const_int 24)))]
)
;; ----------------------------------------------------------------------
@@ -2585,16 +2930,17 @@
[(return)]
""
"
-{
- mn10300_expand_epilogue ();
- DONE;
-}")
+ {
+ mn10300_expand_epilogue ();
+ DONE;
+ }")
(define_insn "return_internal"
[(const_int 2)
(return)]
""
"rets"
+ [(set_attr "timings" "66")]
)
;; This insn restores the callee saved registers and does a return, it
@@ -2605,12 +2951,15 @@
(return)]
""
"*
-{
- fputs (\"\\tret \", asm_out_file);
- mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
- fprintf (asm_out_file, \",%d\\n\", (int) INTVAL (operands[0]));
- return \"\";
-}"
+ {
+ fputs (\"\\tret \", asm_out_file);
+ mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
+ fprintf (asm_out_file, \",%d\\n\", (int) INTVAL (operands[0]));
+ return \"\";
+ }"
+ ;; Assumes that there will be no more than 8 regs to pop
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 1414) (const_int 1313)))]
)
;; This instruction matches one generated by mn10300_gen_multiple_store()
@@ -2619,14 +2968,17 @@
[(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand 1 "" "")))])]
""
"*
-{
- fputs (\"\\tmovm \", asm_out_file);
- mn10300_print_reg_list (asm_out_file,
- mn10300_store_multiple_operation (operands[0],
- VOIDmode));
- fprintf (asm_out_file, \",(sp)\\n\");
- return \"\";
-}"
+ {
+ fputs (\"\\tmovm \", asm_out_file);
+ mn10300_print_reg_list (asm_out_file,
+ mn10300_store_multiple_operation (operands[0],
+ VOIDmode));
+ fprintf (asm_out_file, \",(sp)\\n\");
+ return \"\";
+ }"
+ ;; Assume that no more than 8 registers will be pushed.
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 99) (const_int 88)))]
)
(define_insn "return"
@@ -2643,6 +2995,7 @@
else
return \"rets\";
}"
+ [(set_attr "timings" "66")]
)
;; Try to combine consecutive updates of the stack pointer (or any
@@ -2727,7 +3080,9 @@
[(set (mem:SI (reg:SI SP_REG)) (pc))
(use (match_operand 0 "" ""))])]
"reload_completed"
- "calls %0\;%0:")
+ "calls %0\;%0:"
+ [(set_attr "timings" "44")]
+)
(define_expand "add_GOT_to_pic_reg"
[(parallel [(set (reg:SI PIC_REG)
diff --git a/gcc/config/mn10300/mn10300.opt b/gcc/config/mn10300/mn10300.opt
index c7e12d75bf3..f2a434ef738 100644
--- a/gcc/config/mn10300/mn10300.opt
+++ b/gcc/config/mn10300/mn10300.opt
@@ -1,6 +1,6 @@
; Options for the Matsushita MN10300 port of the compiler.
-; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+; Copyright (C) 2005, 2007, 2010 Free Software Foundation, Inc.
;
; This file is part of GCC.
;
@@ -26,6 +26,14 @@ mam33-2
Target
Target the AM33/2.0 processor
+mam34
+Target Report
+Target the AM34 processor
+
+mtune=
+Target RejectNegative Joined
+Tune code for the given processor
+
mmult-bug
Target Report Mask(MULT_BUG)
Work around hardware multiply bug
diff --git a/gcc/config/mn10300/t-mn10300 b/gcc/config/mn10300/t-mn10300
index 61e94e32f85..93ed17d9572 100644
--- a/gcc/config/mn10300/t-mn10300
+++ b/gcc/config/mn10300/t-mn10300
@@ -29,8 +29,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT' > fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-MULTILIB_OPTIONS = mam33/mam33-2
-MULTILIB_DIRNAMES = am33 am33-2
+MULTILIB_OPTIONS = mam33/mam33-2/mam34
+MULTILIB_DIRNAMES = am33 am33-2 am34
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/moxie/moxie-protos.h b/gcc/config/moxie/moxie-protos.h
index 3c1027bee58..7d939f58873 100644
--- a/gcc/config/moxie/moxie-protos.h
+++ b/gcc/config/moxie/moxie-protos.h
@@ -23,7 +23,3 @@ extern void moxie_expand_epilogue (void);
extern int moxie_initial_elimination_offset (int, int);
extern void moxie_print_operand (FILE *, rtx, int);
extern void moxie_print_operand_address (FILE *, rtx);
-#ifdef RTX_CODE
-extern rtx moxie_function_arg (CUMULATIVE_ARGS,
- enum machine_mode, tree, int);
-#endif /* RTX_CODE */
diff --git a/gcc/config/moxie/moxie.c b/gcc/config/moxie/moxie.c
index cd2fb88decc..d2a6b665628 100644
--- a/gcc/config/moxie/moxie.c
+++ b/gcc/config/moxie/moxie.c
@@ -409,16 +409,30 @@ moxie_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
/* Return the next register to be used to hold a function argument or
NULL_RTX if there's no more space. */
-rtx
-moxie_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
+static rtx
+moxie_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
{
- if (cum < 8)
- return gen_rtx_REG (mode, cum);
+ if (*cum < 8)
+ return gen_rtx_REG (mode, *cum);
else
return NULL_RTX;
}
+#define MOXIE_FUNCTION_ARG_SIZE(MODE, TYPE) \
+ ((MODE) != BLKmode ? GET_MODE_SIZE (MODE) \
+ : (unsigned) int_size_in_bytes (TYPE))
+
+static void
+moxie_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ *cum = (*cum < MOXIE_R6
+ ? *cum + ((3 + MOXIE_FUNCTION_ARG_SIZE (mode, type)) / 4)
+ : *cum);
+}
+
/* Return non-zero if the function argument described by TYPE is to be
passed by reference. */
@@ -539,6 +553,10 @@ moxie_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
#define TARGET_PASS_BY_REFERENCE moxie_pass_by_reference
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES moxie_arg_partial_bytes
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG moxie_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE moxie_function_arg_advance
#undef TARGET_SETUP_INCOMING_VARARGS
diff --git a/gcc/config/moxie/moxie.h b/gcc/config/moxie/moxie.h
index 30170b430ef..0cfc11b352b 100644
--- a/gcc/config/moxie/moxie.h
+++ b/gcc/config/moxie/moxie.h
@@ -231,11 +231,6 @@ enum reg_class
/* Passing Arguments in Registers */
-/* A C expression that controls whether a function argument is passed
- in a register, and which register. */
-#define FUNCTION_ARG(CUM,MODE,TYPE,NAMED) \
- moxie_function_arg(CUM,MODE,TYPE,NAMED)
-
/* A C type for declaring a variable that is used as the first
argument of `FUNCTION_ARG' and other related values. */
#define CUMULATIVE_ARGS unsigned int
@@ -253,14 +248,6 @@ enum reg_class
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,FNDECL,N_NAMED_ARGS) \
(CUM = MOXIE_R0)
-#define MOXIE_FUNCTION_ARG_SIZE(MODE, TYPE) \
- ((MODE) != BLKmode ? GET_MODE_SIZE (MODE) \
- : (unsigned) int_size_in_bytes (TYPE))
-
-#define FUNCTION_ARG_ADVANCE(CUM,MODE,TYPE,NAMED) \
- (CUM = (CUM < MOXIE_R6 ? \
- CUM + ((3 + MOXIE_FUNCTION_ARG_SIZE(MODE,TYPE))/4) : CUM ))
-
/* How Scalar Function Values Are Returned */
/* STACK AND CALLING */
diff --git a/gcc/config/pdp11/pdp11-protos.h b/gcc/config/pdp11/pdp11-protos.h
index 3b0e59a6200..a8da5a666bf 100644
--- a/gcc/config/pdp11/pdp11-protos.h
+++ b/gcc/config/pdp11/pdp11-protos.h
@@ -31,7 +31,11 @@ extern const char *output_move_quad (rtx *);
extern const char *output_block_move (rtx *);
extern const char *output_jump (enum rtx_code, int, int);
extern void print_operand_address (FILE *, rtx);
-extern int pdp11_register_move_cost (enum reg_class, enum reg_class);
+extern bool pdp11_cannot_change_mode_class (enum machine_mode,
+ enum machine_mode, enum reg_class);
+extern bool pdp11_secondary_memory_needed (reg_class_t, reg_class_t,
+ enum machine_mode);
+
#endif /* RTX_CODE */
extern void output_ascii (FILE *, const char *, int);
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 6850baafc5c..946d7ed973b 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -216,7 +216,17 @@ static const struct default_options pdp11_option_optimization_table[] =
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
-struct gcc_target targetm = TARGET_INITIALIZER;
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD pdp11_secondary_reload
+
+#undef TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST pdp11_register_move_cost
+
+#undef TARGET_PREFERRED_RELOAD_CLASS
+#define TARGET_PREFERRED_RELOAD_CLASS pdp11_preferred_reload_class
+
+#undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
+#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS pdp11_preferred_output_reload_class
/* Implement TARGET_HANDLE_OPTION. */
@@ -417,7 +427,7 @@ pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
/* get ACs */
for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
- if (df_regs_ever_live_p (i) && call_used_regs[i])
+ if (df_regs_ever_live_p (i) && ! call_used_regs[i])
via_ac = i;
for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
@@ -685,12 +695,6 @@ output_move_quad (rtx *operands)
gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
- /* check if we move a CPU reg to an FPU reg, or vice versa! */
- if (optype0 == REGOP && optype1 == REGOP)
- /* bogus - 64 bit cannot reside in CPU! */
- gcc_assert (!CPU_REG_P(REGNO(operands[0]))
- && !CPU_REG_P (REGNO(operands[1])));
-
if (optype0 == REGOP || optype1 == REGOP)
{
/* check for use of clrd????
@@ -895,14 +899,13 @@ output_ascii (FILE *file, const char *p, int size)
}
-/* --- stole from out-vax, needs changes */
-
void
print_operand_address (FILE *file, register rtx addr)
{
- register rtx reg1, reg2, breg, ireg;
+ register rtx breg;
rtx offset;
-
+ int again = 0;
+
retry:
switch (GET_CODE (addr))
@@ -913,6 +916,7 @@ print_operand_address (FILE *file, register rtx addr)
else
fprintf (file, "@");
addr = XEXP (addr, 0);
+ again = 1;
goto retry;
case REG:
@@ -930,8 +934,7 @@ print_operand_address (FILE *file, register rtx addr)
break;
case PLUS:
- reg1 = 0; reg2 = 0;
- ireg = 0; breg = 0;
+ breg = 0;
offset = 0;
if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
|| GET_CODE (XEXP (addr, 0)) == MEM)
@@ -947,32 +950,20 @@ print_operand_address (FILE *file, register rtx addr)
}
if (GET_CODE (addr) != PLUS)
;
- else if (GET_CODE (XEXP (addr, 0)) == MULT)
- {
- reg1 = XEXP (addr, 0);
- addr = XEXP (addr, 1);
- }
- else if (GET_CODE (XEXP (addr, 1)) == MULT)
- {
- reg1 = XEXP (addr, 1);
- addr = XEXP (addr, 0);
- }
else if (GET_CODE (XEXP (addr, 0)) == REG)
{
- reg1 = XEXP (addr, 0);
+ breg = XEXP (addr, 0);
addr = XEXP (addr, 1);
}
else if (GET_CODE (XEXP (addr, 1)) == REG)
{
- reg1 = XEXP (addr, 1);
+ breg = XEXP (addr, 1);
addr = XEXP (addr, 0);
}
- if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
+ if (GET_CODE (addr) == REG)
{
- if (reg1 == 0)
- reg1 = addr;
- else
- reg2 = addr;
+ gcc_assert (breg == 0);
+ breg = addr;
addr = 0;
}
if (offset != 0)
@@ -980,44 +971,22 @@ print_operand_address (FILE *file, register rtx addr)
gcc_assert (addr == 0);
addr = offset;
}
- if (reg1 != 0 && GET_CODE (reg1) == MULT)
- {
- breg = reg2;
- ireg = reg1;
- }
- else if (reg2 != 0 && GET_CODE (reg2) == MULT)
- {
- breg = reg1;
- ireg = reg2;
- }
- else if (reg2 != 0 || GET_CODE (addr) == MEM)
- {
- breg = reg2;
- ireg = reg1;
- }
- else
- {
- breg = reg1;
- ireg = reg2;
- }
if (addr != 0)
- output_address (addr);
+ output_addr_const_pdp11 (file, addr);
if (breg != 0)
{
gcc_assert (GET_CODE (breg) == REG);
fprintf (file, "(%s)", reg_names[REGNO (breg)]);
}
- if (ireg != 0)
- {
- if (GET_CODE (ireg) == MULT)
- ireg = XEXP (ireg, 0);
- gcc_assert (GET_CODE (ireg) == REG);
- gcc_unreachable(); /* ??? */
- fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
- }
break;
default:
+ if (!again && GET_CODE (addr) == CONST_INT)
+ {
+ /* Absolute (integer number) address. */
+ if (!TARGET_UNIX_ASM)
+ fprintf (file, "@$");
+ }
output_addr_const_pdp11 (file, addr);
}
}
@@ -1054,22 +1023,23 @@ static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
/* NO MUL GEN LFPU NLFPU FPU ALL */
/* NO */ { 0, 0, 0, 0, 0, 0, 0},
-/* MUL */ { 0, 2, 2, 10, 22, 22, 22},
-/* GEN */ { 0, 2, 2, 10, 22, 22, 22},
-/* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
-/* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
-/* FPU */ { 0, 22, 22, 2, 2, 2, 22},
-/* ALL */ { 0, 22, 22, 10, 22, 22, 22}
+/* MUL */ { 0, 2, 2, 22, 22, 22, 22},
+/* GEN */ { 0, 2, 2, 22, 22, 22, 22},
+/* LFPU */ { 0, 22, 22, 2, 2, 2, 22},
+/* NLFPU */ { 0, 22, 22, 2, 10, 10, 22},
+/* FPU */ { 0, 22, 22, 2, 10, 10, 22},
+/* ALL */ { 0, 22, 22, 22, 22, 22, 22}
} ;
/* -- note that some moves are tremendously expensive,
because they require lots of tricks! do we have to
charge the costs incurred by secondary reload class
- -- as we do here with 22 -- or not ? */
+ -- as we do here with 10 -- or not ? */
-int
-pdp11_register_move_cost (enum reg_class c1, enum reg_class c2)
+static int
+pdp11_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+ reg_class_t c1, reg_class_t c2)
{
return move_costs[(int)c1][(int)c2];
}
@@ -1634,6 +1604,108 @@ legitimate_const_double_p (rtx address)
return 0;
}
+/* Implement CANNOT_CHANGE_MODE_CLASS. */
+bool
+pdp11_cannot_change_mode_class (enum machine_mode from,
+ enum machine_mode to,
+ enum reg_class rclass)
+{
+ /* Also, FPU registers contain a whole float value and the parts of
+ it are not separately accessible.
+
+ So we disallow all mode changes involving FPRs. */
+ if (FLOAT_MODE_P (from) != FLOAT_MODE_P (to))
+ return true;
+
+ return reg_classes_intersect_p (FPU_REGS, rclass);
+}
+
+/* TARGET_PREFERRED_RELOAD_CLASS
+
+ Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class.
+
+loading is easier into LOAD_FPU_REGS than FPU_REGS! */
+
+static reg_class_t
+pdp11_preferred_reload_class (rtx x, reg_class_t class)
+{
+ if (class == FPU_REGS)
+ return LOAD_FPU_REGS;
+ if (class == ALL_REGS)
+ {
+ if (FLOAT_MODE_P (GET_MODE (x)))
+ return LOAD_FPU_REGS;
+ else
+ return GENERAL_REGS;
+ }
+ return class;
+}
+
+/* TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
+
+ Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class.
+
+loading is easier into LOAD_FPU_REGS than FPU_REGS! */
+
+static reg_class_t
+pdp11_preferred_output_reload_class (rtx x, reg_class_t class)
+{
+ if (class == FPU_REGS)
+ return LOAD_FPU_REGS;
+ if (class == ALL_REGS)
+ {
+ if (FLOAT_MODE_P (GET_MODE (x)))
+ return LOAD_FPU_REGS;
+ else
+ return GENERAL_REGS;
+ }
+ return class;
+}
+
+
+/* TARGET_SECONDARY_RELOAD.
+
+ FPU registers AC4 and AC5 (class NO_LOAD_FPU_REGS) require an
+ intermediate register (AC0-AC3: LOAD_FPU_REGS). Everything else
+ can be loade/stored directly. */
+reg_class_t
+pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED,
+ rtx x,
+ reg_class_t reload_class,
+ enum machine_mode reload_mode ATTRIBUTE_UNUSED,
+ secondary_reload_info *sri ATTRIBUTE_UNUSED)
+{
+ if (reload_class != NO_LOAD_FPU_REGS || GET_CODE (x) != REG ||
+ REGNO_REG_CLASS (REGNO (x)) == LOAD_FPU_REGS)
+ return NO_REGS;
+
+ return LOAD_FPU_REGS;
+}
+
+/* Target routine to check if register to register move requires memory.
+
+ The answer is yes if we're going between general register and FPU
+ registers. The mode doesn't matter in making this check.
+*/
+bool
+pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ int fromfloat = (c1 == LOAD_FPU_REGS || c1 == NO_LOAD_FPU_REGS ||
+ c1 == FPU_REGS);
+ int tofloat = (c2 == LOAD_FPU_REGS || c2 == NO_LOAD_FPU_REGS ||
+ c2 == FPU_REGS);
+
+ return (fromfloat != tofloat);
+}
+
+
/* A copy of output_addr_const modified for pdp11 expression syntax.
output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
use, and for debugging output, which we don't support with this port either.
@@ -1751,7 +1823,7 @@ pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
ac0 if DFmode and FPU present - compatibility problem with
libraries for non-floating point.... */
return (TYPE_MODE (type) == DImode
- || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));
+ || (FLOAT_MODE_P (TYPE_MODE (type)) && ! TARGET_AC0));
}
/* Worker function for TARGET_FUNCTION_VALUE.
@@ -1795,8 +1867,8 @@ pdp11_function_value_regno_p (const unsigned int regno)
the following should work for shared I/D:
- MV #STATIC, $4 0x940Y 0x0000 <- STATIC; Y = STATIC_CHAIN_REGNUM
- JMP FUNCTION 0x0058 0x0000 <- FUNCTION
+ MOV #STATIC, $4 01270Y 0x0000 <- STATIC; Y = STATIC_CHAIN_REGNUM
+ JMP @#FUNCTION 000137 0x0000 <- FUNCTION
*/
static void
@@ -1808,11 +1880,11 @@ pdp11_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
gcc_assert (!TARGET_SPLIT);
mem = adjust_address (m_tramp, HImode, 0);
- emit_move_insn (mem, GEN_INT (0x9400+STATIC_CHAIN_REGNUM));
+ emit_move_insn (mem, GEN_INT (012700+STATIC_CHAIN_REGNUM));
mem = adjust_address (m_tramp, HImode, 2);
emit_move_insn (mem, chain_value);
mem = adjust_address (m_tramp, HImode, 4);
- emit_move_insn (mem, GEN_INT (0x0058));
+ emit_move_insn (mem, GEN_INT (000137));
emit_move_insn (mem, fnaddr);
}
@@ -1854,3 +1926,5 @@ pdp11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
? GET_MODE_SIZE (mode)
: int_size_in_bytes (type));
}
+
+struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h
index 1b1e713344b..08b9d675cde 100644
--- a/gcc/config/pdp11/pdp11.h
+++ b/gcc/config/pdp11/pdp11.h
@@ -215,15 +215,19 @@ extern const struct real_format pdp11_d_format;
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- On the pdp, the cpu registers can hold any mode - check alignment
+ On the pdp, the cpu registers can hold any mode other than float
+ (because otherwise we may end up being asked to move from CPU to FPU
+ register, which isn't a valid operation on the PDP11).
+ For CPU registers, check alignment.
- FPU can only hold DF - simplifies life!
+ FPU accepts SF and DF but actually holds a DF - simplifies life!
*/
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(((REGNO) <= PC_REGNUM)? \
((GET_MODE_BITSIZE(MODE) <= 16) \
- || (GET_MODE_BITSIZE(MODE) >= 32 && !((REGNO) & 1))) \
- :(MODE) == DFmode)
+ || (GET_MODE_BITSIZE(MODE) >= 32 && \
+ !((REGNO) & 1) && !FLOAT_MODE_P (MODE))) \
+ :FLOAT_MODE_P (MODE))
/* Value is 1 if it is a good idea to tie two pseudo registers
@@ -322,18 +326,9 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
#define IRA_COVER_CLASSES { GENERAL_REGS, FPU_REGS, LIM_REG_CLASSES }
-/* Given an rtx X being reloaded into a reg required to be
- in class CLASS, return the class of reg to actually use.
- In general this is just CLASS; but on some machines
- in some cases it is preferable to use a more restrictive class.
-
-loading is easier into LOAD_FPU_REGS than FPU_REGS! */
-
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
-(((CLASS) != FPU_REGS)?(CLASS):LOAD_FPU_REGS)
-
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,x) \
-(((CLASS) == NO_LOAD_FPU_REGS && !(REG_P(x) && LOAD_FPU_REG_P(REGNO(x))))?LOAD_FPU_REGS:NO_REGS)
+/* Hook for testing if memory is needed for moving between registers. */
+#define SECONDARY_MEMORY_NEEDED(class1, class2, m) \
+ pdp11_secondary_memory_needed (class1, class2, m)
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS. */
@@ -343,6 +338,8 @@ loading is easier into LOAD_FPU_REGS than FPU_REGS! */
1 \
)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ pdp11_cannot_change_mode_class (FROM, TO, CLASS)
/* Stack layout; function entry, exit and calling. */
@@ -386,7 +383,7 @@ extern int current_first_parm_offset;
If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is 0. */
#define BASE_RETURN_VALUE_REG(MODE) \
- ((MODE) == DFmode ? 8 : 0)
+ (FLOAT_MODE_P (MODE) ? AC0_REGNUM : RETVAL_REGNUM)
/* 1 if N is a possible register number for function argument passing.
- not used on pdp */
@@ -674,10 +671,6 @@ extern int may_call_alloca;
/* #define NO_FUNCTION_CSE */
-/* cost of moving one register class to another */
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
- pdp11_register_move_cost (CLASS1, CLASS2)
-
/* Tell emit-rtl.c how to initialize special values on a per-function base. */
extern struct rtx_def *cc0_reg_rtx;
diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md
index 53097b75a77..2f73390a501 100644
--- a/gcc/config/pdp11/pdp11.md
+++ b/gcc/config/pdp11/pdp11.md
@@ -25,6 +25,7 @@
(define_constants
[
;; Register numbers
+ (RETVAL_REGNUM 0)
(FRAME_POINTER_REGNUM 5)
(STACK_POINTER_REGNUM 6)
(PC_REGNUM 7)
@@ -42,6 +43,11 @@
;; HI is 16 bit
;; QI is 8 bit
+;; Integer modes supported on the PDP11, with a mapping from machine mode
+;; to mnemonic suffix. SImode and DImode always are special cases.
+(define_mode_iterator PDPint [QI HI])
+(define_mode_attr isfx [(QI "b") (HI "")])
+
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
@@ -196,7 +202,7 @@
(define_expand "cbranchdf4"
[(set (cc0)
(compare (match_operand:DF 1 "general_operand")
- (match_operand:DF 2 "general_operand")))
+ (match_operand:DF 2 "register_or_const0_operand")))
(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
[(cc0) (const_int 0)])
@@ -276,7 +282,7 @@
;; Move instructions
(define_insn "movdi"
- [(set (match_operand:DI 0 "general_operand" "=g,rm,o")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g,rm,o")
(match_operand:DI 1 "general_operand" "m,r,a"))]
""
"* return output_move_quad (operands);"
@@ -284,7 +290,7 @@
[(set_attr "length" "32,32,32")])
(define_insn "movsi"
- [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,rm,m")
(match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
""
"* return output_move_double (operands);"
@@ -293,7 +299,7 @@
[(set_attr "length" "4,6,8,16,16")])
(define_insn "movhi"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
""
"*
@@ -306,7 +312,7 @@
[(set_attr "length" "2,4,4,6")])
(define_insn "movqi"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(match_operand:QI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
""
"*
@@ -318,11 +324,9 @@
}"
[(set_attr "length" "2,4,4,6")])
-;; do we have to supply all these moves? e.g. to
-;; NO_LOAD_FPU_REGs ?
(define_insn "movdf"
- [(set (match_operand:DF 0 "general_operand" "=a,fR,a,Q,g")
- (match_operand:DF 1 "general_operand" "fFR,a,Q,a,g"))]
+ [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
+ (match_operand:DF 1 "float_operand" "fFR,a,Q,a,g"))]
"TARGET_FPU"
"* if (which_alternative ==0 || which_alternative == 2)
return \"ldd %1, %0\";
@@ -334,11 +338,17 @@
[(set_attr "length" "2,2,10,10,32")])
(define_insn "movsf"
- [(set (match_operand:SF 0 "general_operand" "=g,r,g")
- (match_operand:SF 1 "general_operand" "r,rmF,g"))]
+ [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
+ (match_operand:SF 1 "float_operand" "fFR,a,Q,a,g"))]
"TARGET_FPU"
- "* return output_move_double (operands);"
- [(set_attr "length" "16,16,16")])
+ "* if (which_alternative ==0 || which_alternative == 2)
+ return \"{ldcfd|movof} %1, %0\";
+ else if (which_alternative == 1 || which_alternative == 3)
+ return \"{stcdf|movfo} %1, %0\";
+ else
+ return output_move_double (operands); "
+;; just a guess..
+ [(set_attr "length" "2,2,10,10,16")])
;; maybe fiddle a bit with move_ratio, then
;; let constraints only accept a register ...
@@ -386,15 +396,11 @@
;;- truncation instructions
(define_insn "truncdfsf2"
- [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
- (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
+ [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
"TARGET_FPU"
"* if (which_alternative ==0)
{
- output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
- output_asm_insn(\"mov (sp)+, %0\", operands);
- operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
- output_asm_insn(\"mov (sp)+, %0\", operands);
return \"\";
}
else if (which_alternative == 1)
@@ -402,11 +408,11 @@
else
return \"{stcdf|movfo} %1, %0\";
"
- [(set_attr "length" "6,2,4")])
+ [(set_attr "length" "0,2,4")])
(define_expand "truncsihi2"
- [(set (match_operand:HI 0 "general_operand" "=g")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(subreg:HI
(match_operand:SI 1 "general_operand" "or")
0))]
@@ -417,7 +423,7 @@
;;- zero extension instructions
(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
""
"bic $0177400, %0"
@@ -439,14 +445,14 @@
;;- sign extension instructions
(define_insn "extendsfdf2"
- [(set (match_operand:DF 0 "register_operand" "=a,a,a")
- (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
+ [(set (match_operand:DF 0 "register_operand" "=f,a,a")
+ (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
"TARGET_FPU"
"@
- mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
+ /* nothing */
{ldcfd|movof} %1, %0
{ldcfd|movof} %1, %0"
- [(set_attr "length" "4,2,4")])
+ [(set_attr "length" "0,2,4")])
;; does movb sign extend in register-to-register move?
(define_insn "extendqihi2"
@@ -479,13 +485,13 @@
;; unconditionally, and then match dependent on CPU type:
(define_expand "extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=g")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
""
"")
(define_insn "" ; "extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=o,<,r")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
(sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
"TARGET_40_PLUS"
"*
@@ -604,7 +610,7 @@
;; cut float to int
(define_insn "fix_truncdfsi2"
- [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
"TARGET_FPU"
"* if (which_alternative ==0)
@@ -625,7 +631,7 @@
[(set_attr "length" "10,6,8")])
(define_insn "fix_truncdfhi2"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
"TARGET_FPU"
"{stcdi|movfi} %1, %0"
@@ -644,7 +650,7 @@
[(set_attr "length" "2,4,10")])
(define_insn "addsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o,r,r,r,o,o,o")
(plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
(match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
""
@@ -694,7 +700,7 @@
[(set_attr "length" "6,10,12,16,6,2,10,10,6,16")])
(define_insn "addhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
(match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
""
@@ -713,7 +719,7 @@
[(set_attr "length" "2,4,4,6")])
(define_insn "addqi3"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
(match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
""
@@ -746,7 +752,7 @@
[(set_attr "length" "2,4")])
(define_insn "subsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
(minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
(match_operand:SI 2 "general_operand" "r,o,r,o")))]
""
@@ -780,7 +786,7 @@
[(set_attr "length" "6,10,12,16")])
(define_insn "subhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
(match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
""
@@ -793,7 +799,7 @@
[(set_attr "length" "2,4,4,6")])
(define_insn "subqi3"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
(match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
""
@@ -808,73 +814,44 @@
;;;;- and instructions
;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
-(define_insn "andsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
- (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
- (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
+(define_expand "and<mode>3"
+ [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
+ (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
+ (match_operand:PDPint 2 "general_operand" "")))]
""
- "*
-{ /* Here we trust that operands don't overlap
-
- or is lateoperands the low word?? - looks like it! */
+ "
+{
+ rtx op1 = operands[1];
- rtx lateoperands[3];
-
- lateoperands[0] = operands[0];
+ /* If there is a constant argument, complement that one.
+ Similarly, if one of the inputs is the same as the output,
+ complement the other input. */
+ if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
+ rtx_equal_p (operands[0], operands[1]))
+ {
+ operands[1] = operands[2];
+ operands[2] = op1;
+ op1 = operands[1];
+ }
- if (REG_P (operands[0]))
- operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
+ if (CONST_INT_P (op1))
+ operands[1] = GEN_INT (~INTVAL (op1));
else
- operands[0] = adjust_address (operands[0], HImode, 2);
-
- if (! CONSTANT_P(operands[2]))
- {
- lateoperands[2] = operands[2];
-
- if (REG_P (operands[2]))
- operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
- else
- operands[2] = adjust_address (operands[2], HImode, 2);
-
- output_asm_insn (\"bic %2, %0\", operands);
- output_asm_insn (\"bic %2, %0\", lateoperands);
- return \"\";
- }
-
- lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
-
- /* these have different lengths, so we should have
- different constraints! */
- if (INTVAL(operands[2]))
- output_asm_insn (\"bic %2, %0\", operands);
-
- if (INTVAL(lateoperands[2]))
- output_asm_insn (\"bic %2, %0\", lateoperands);
-
- return \"\";
-}"
- [(set_attr "length" "4,8,8,12,4,4,8,6,6,12")])
-
-(define_insn "andhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
- (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
- (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
- ""
- "bic %2, %0"
- [(set_attr "length" "2,4,4,6")])
+ operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
+}")
-(define_insn "andqi3"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
- (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
- (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
+(define_insn "*bic<mode>"
+ [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
+ (and:PDPint
+ (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
+ (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
""
- "bicb %2, %0"
+ "bic<PDPint:isfx> %1, %0"
[(set_attr "length" "2,4,4,6")])
;;- Bit set (inclusive or) instructions
(define_insn "iorsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o,r,r,r,o,o,o")
(ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
(match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
""
@@ -922,7 +899,7 @@
[(set_attr "length" "4,8,8,12,4,4,8,6,6,12")])
(define_insn "iorhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
(match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
""
@@ -930,7 +907,7 @@
[(set_attr "length" "2,4,4,6")])
(define_insn "iorqi3"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
(match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
""
@@ -957,15 +934,13 @@
output_asm_insn (\"xor %2, %0\", operands);
output_asm_insn (\"xor %2, %0\", lateoperands);
-
- return \"\";
}
-
+ return \"\";
}"
[(set_attr "length" "4")])
(define_insn "xorhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(xor:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "register_operand" "r,r")))]
"TARGET_40_PLUS"
@@ -975,14 +950,14 @@
;;- one complement instructions
(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(not:HI (match_operand:HI 1 "general_operand" "0,0")))]
""
"com %0"
[(set_attr "length" "2,4")])
(define_insn "one_cmplqi2"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,rR")
(not:QI (match_operand:QI 1 "general_operand" "0,g")))]
""
"@
@@ -1014,7 +989,7 @@
;; asl
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(ashift:HI (match_operand:HI 1 "general_operand" "0,0")
(const_int 1)))]
""
@@ -1027,7 +1002,7 @@
;; asr
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(ashift:HI (match_operand:HI 1 "general_operand" "0,0")
(const_int -1)))]
""
@@ -1036,7 +1011,7 @@
;; lsr
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
(const_int 1)))]
""
@@ -1070,7 +1045,7 @@
;; shift by one cheap - so let's do that, if
;; space doesn't matter
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=r")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
(ashift:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "expand_shift_operand" "O")))]
"! optimize_size"
@@ -1091,7 +1066,7 @@
;; aslb
(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=r,o")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
(ashift:QI (match_operand:QI 1 "general_operand" "0,0")
(match_operand:HI 2 "const_int_operand" "n,n")))]
""
@@ -1113,7 +1088,7 @@
;;; asr
;(define_insn ""
-; [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+; [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
; (const_int 1)))]
; ""
@@ -1122,7 +1097,7 @@
;; asrb
(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=r,o")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
(ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
(match_operand:HI 2 "const_int_operand" "n,n")))]
""
@@ -1193,14 +1168,14 @@
;; absolute
(define_insn "absdf2"
- [(set (match_operand:DF 0 "general_operand" "=fR,Q")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
(abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
"TARGET_FPU"
"{absd|absf} %0"
[(set_attr "length" "2,4")])
(define_insn "abshi2"
- [(set (match_operand:HI 0 "general_operand" "=r,o")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,o")
(abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
"TARGET_ABSHI_BUILTIN"
"*
@@ -1227,7 +1202,7 @@
; -- just a thought - don't have time to check
;
;(define_expand "abshi2"
-; [(match_operand:HI 0 "general_operand" "")
+; [(match_operand:HI 0 "nonimmediate_operand" "")
; (match_operand:HI 1 "general_operand" "")]
; ""
; "
@@ -1257,7 +1232,7 @@
;; negate insns
(define_insn "negdf2"
- [(set (match_operand:DF 0 "general_operand" "=fR,Q")
+ [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
(neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
"TARGET_FPU"
"{negd|negf} %0"
@@ -1287,14 +1262,14 @@
[(set_attr "length" "10")])
(define_insn "neghi2"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
""
"neg %0"
[(set_attr "length" "2,4")])
(define_insn "negqi2"
- [(set (match_operand:QI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
(neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
""
"negb %0"
@@ -1381,7 +1356,7 @@
(define_insn "muldf3"
[(set (match_operand:DF 0 "register_operand" "=a,a,a")
(mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
- (match_operand:DF 2 "general_operand" "fR,Q,F")))]
+ (match_operand:DF 2 "float_operand" "fR,Q,F")))]
"TARGET_FPU"
"{muld|mulf} %2, %0"
[(set_attr "length" "2,4,10")])
@@ -1395,7 +1370,7 @@
(define_insn "mulhi3"
[(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
(mult:HI (match_operand:HI 1 "register_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rR,Qi")))]
+ (match_operand:HI 2 "float_operand" "rR,Qi")))]
"TARGET_40_PLUS"
"mul %2, %0"
[(set_attr "length" "2,4")])
@@ -1403,7 +1378,7 @@
;; 32 bit result
(define_expand "mulhisi3"
[(set (match_dup 3)
- (match_operand:HI 1 "general_operand" "g,g"))
+ (match_operand:HI 1 "nonimmediate_operand" "g,g"))
(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
(mult:SI (truncate:HI
(match_dup 0))
@@ -1441,15 +1416,15 @@
(define_expand "divhi3"
[(set (subreg:HI (match_dup 1) 0)
- (div:HI (match_operand:SI 1 "general_operand" "0")
+ (div:HI (match_operand:SI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "g")))
- (set (match_operand:HI 0 "general_operand" "=r")
+ (set (match_operand:HI 0 "register_operand" "=r")
(subreg:HI (match_dup 1) 0))]
"TARGET_40_PLUS"
"")
(define_insn ""
- [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
+ [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
(div:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
"TARGET_40_PLUS"
@@ -1458,15 +1433,15 @@
(define_expand "modhi3"
[(set (subreg:HI (match_dup 1) 2)
- (mod:HI (match_operand:SI 1 "general_operand" "0")
+ (mod:HI (match_operand:SI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "g")))
- (set (match_operand:HI 0 "general_operand" "=r")
+ (set (match_operand:HI 0 "register_operand" "=r")
(subreg:HI (match_dup 1) 2))]
"TARGET_40_PLUS"
"")
(define_insn ""
- [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 2)
+ [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
(mod:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
"TARGET_40_PLUS"
@@ -1475,20 +1450,20 @@
;(define_expand "divmodhi4"
; [(parallel [(set (subreg:HI (match_dup 1) 0)
-; (div:HI (match_operand:SI 1 "general_operand" "0")
+; (div:HI (match_operand:SI 1 "register_operand" "0")
; (match_operand:HI 2 "general_operand" "g")))
; (set (subreg:HI (match_dup 1) 2)
; (mod:HI (match_dup 1)
; (match_dup 2)))])
-; (set (match_operand:HI 3 "general_operand" "=r")
+; (set (match_operand:HI 3 "register_operand" "=r")
; (subreg:HI (match_dup 1) 2))
-; (set (match_operand:HI 0 "general_operand" "=r")
+; (set (match_operand:HI 0 "register_operand" "=r")
; (subreg:HI (match_dup 1) 0))]
; "TARGET_40_PLUS"
; "")
;
;(define_insn ""
-; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
+; [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
; (div:HI (match_operand:SI 1 "general_operand" "0")
; (match_operand:HI 2 "general_operand" "g")))
; (set (subreg:HI (match_dup 0) 2)
diff --git a/gcc/config/pdp11/predicates.md b/gcc/config/pdp11/predicates.md
index 3864bbb7b15..8b24ba4fc5c 100644
--- a/gcc/config/pdp11/predicates.md
+++ b/gcc/config/pdp11/predicates.md
@@ -35,3 +35,21 @@
sh = INTVAL (op);
return (abs (sh) > 1 && abs (sh) <= 4);
})
+
+;; Accept anything general_operand accepts, except that registers must
+;; be FPU registers.
+(define_predicate "float_operand"
+ (if_then_else (match_code "reg")
+ (ior
+ (match_test "REGNO_REG_CLASS (REGNO (op)) == LOAD_FPU_REGS")
+ (match_test "REGNO_REG_CLASS (REGNO (op)) == NO_LOAD_FPU_REGS"))
+ (match_test "general_operand (op, mode)")))
+
+;; Accept anything nonimmediate_operand accepts, except that registers must
+;; be FPU registers.
+(define_predicate "float_nonimm_operand"
+ (if_then_else (match_code "reg")
+ (ior
+ (match_test "REGNO_REG_CLASS (REGNO (op)) == LOAD_FPU_REGS")
+ (match_test "REGNO_REG_CLASS (REGNO (op)) == NO_LOAD_FPU_REGS"))
+ (match_test "nonimmediate_operand (op, mode)")))
diff --git a/gcc/config/picochip/picochip.c b/gcc/config/picochip/picochip.c
index f8584f31c04..4f09cd551c1 100644
--- a/gcc/config/picochip/picochip.c
+++ b/gcc/config/picochip/picochip.c
@@ -2299,8 +2299,7 @@ picochip_is_short_branch (rtx insn)
int isRealShortBranch = (get_attr_length(insn) == SHORT_BRANCH_LENGTH);
return (isRealShortBranch ||
- (!isRealShortBranch &&
- picochip_current_vliw_state.num_insns_in_packet > 1));
+ picochip_current_vliw_state.num_insns_in_packet > 1);
}
/* Output a compare-and-branch instruction (matching the cbranch
diff --git a/gcc/config/score/score.h b/gcc/config/score/score.h
index 98f6d7dbe03..49887040014 100644
--- a/gcc/config/score/score.h
+++ b/gcc/config/score/score.h
@@ -569,21 +569,6 @@ extern enum reg_class score_char_to_class[256];
#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1
/* Passing Arguments in Registers */
-/* Determine where to put an argument to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- score_function_arg (&CUM, MODE, TYPE, NAMED)
-
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the
type `int' suffices and can hold the number of bytes of argument so far. */
@@ -602,12 +587,6 @@ typedef struct score_args
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, n_named_args) \
score_init_cumulative_args (&CUM, FNTYPE, LIBNAME)
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- score_function_arg_advance (&CUM, MODE, TYPE, NAMED)
-
/* 1 if N is a possible register number for function argument passing.
We have no FP argument registers when soft-float. When FP registers
are 32 bits, we can't directly reference the odd numbered ones. */
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 40587b5ab84..54e7be84947 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -8149,12 +8149,13 @@ sh_dwarf_register_span (rtx reg)
static enum machine_mode
sh_promote_function_mode (const_tree type, enum machine_mode mode,
int *punsignedp, const_tree funtype,
- int for_return ATTRIBUTE_UNUSED)
+ int for_return)
{
if (sh_promote_prototypes (funtype))
return promote_mode (type, mode, punsignedp);
else
- return mode;
+ return default_promote_function_mode (type, mode, punsignedp, funtype,
+ for_return);
}
static bool
diff --git a/gcc/config/sparc/sol2-unwind.h b/gcc/config/sparc/sol2-unwind.h
index c98dc4dc088..aa1358dfae5 100644
--- a/gcc/config/sparc/sol2-unwind.h
+++ b/gcc/config/sparc/sol2-unwind.h
@@ -1,5 +1,5 @@
/* DWARF2 EH unwinding support for SPARC Solaris.
- Copyright (C) 2009 Free Software Foundation, Inc.
+ Copyright (C) 2009, 2010 Free Software Foundation, Inc.
This file is part of GCC.
@@ -118,7 +118,27 @@ sparc64_fallback_frame_state (struct _Unwind_Context *context,
unsigned int cuh_pattern
= *(unsigned int *)(*(unsigned long *)(this_cfa + 15*8) - 4);
- if (cuh_pattern == 0x9410001a || cuh_pattern == 0x94100013)
+ if (cuh_pattern == 0xd25fa7ef)
+ {
+ /* This matches the call_user_handler pattern for Solaris 10.
+ There are 2 cases so we look for the return address of the
+ caller's caller frame in order to do more pattern matching. */
+ unsigned int sah_pattern
+ = *(unsigned int *)(*(unsigned long *)(this_cfa + 176 + 15*8) - 4);
+
+ if (sah_pattern == 0x92100019)
+ /* This is the same setup as for Solaris 9, see below. */
+ regs_off = 176 + 176 + 176 + 304;
+ else
+ /* We need to move up three frames (the kernel frame, the
+ call_user_handler frame, the __sighndlr frame). Two of them
+ have the minimum stack frame size (kernel and __sighndlr
+ frames) of 176 bytes, and there is another with a stack frame
+ of 304 bytes (the call_user_handler frame). The ucontext_t
+ structure is after this offset. */
+ regs_off = 176 + 176 + 304;
+ }
+ else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x94100013)
/* This matches the call_user_handler pattern for Solaris 9 and
for Solaris 8 running inside Solaris Containers respectively.
We need to move up four frames (the kernel frame, the signal
@@ -152,7 +172,7 @@ sparc64_fallback_frame_state (struct _Unwind_Context *context,
fpu_save_off = regs_off + (8*10) + 176;
/* The fpregs field contains 32 extended words at the beginning that
- contain the fpu state. Then there are 2 extended words and two
+ contain the FPU state. Then there are 2 extended words and two
bytes. */
fpu_save = *(unsigned char *)(this_cfa + fpu_save_off + (8*32) + (2*8) + 2);
@@ -195,7 +215,7 @@ sparc64_fallback_frame_state (struct _Unwind_Context *context,
fs->regs.reg[i + 16].loc.offset = i*8;
}
- /* Check whether we need to restore fpu registers. */
+ /* Check whether we need to restore FPU registers. */
if (fpu_save)
{
for (i = 0; i < 64; i++)
@@ -347,14 +367,25 @@ sparc_fallback_frame_state (struct _Unwind_Context *context,
= *(unsigned int *)(*(unsigned int *)(this_cfa + 15*4) - 4);
if (cuh_pattern == 0xd407a04c)
- /* This matches the call_user_handler pattern for Solaris 10.
- We need to move up three frames (the kernel frame, the
- call_user_handler frame, the __sighndlr frame). Two of them
- have the minimum stack frame size (kernel and __sighndlr
- frames) of 96 bytes, and there is another with a stack frame
- of 160 bytes (the call_user_handler frame). The ucontext_t
- structure is after this offset. */
- regs_off = 96 + 96 + 160;
+ {
+ /* This matches the call_user_handler pattern for Solaris 10.
+ There are 2 cases so we look for the return address of the
+ caller's caller frame in order to do more pattern matching. */
+ unsigned int sah_pattern
+ = *(unsigned int *)(*(unsigned int *)(this_cfa + 96 + 15*4) - 4);
+
+ if (sah_pattern == 0x92100019)
+ /* This is the same setup as for Solaris 9, see below. */
+ regs_off = 96 + 96 + 96 + 160;
+ else
+ /* We need to move up three frames (the kernel frame, the
+ call_user_handler frame, the __sighndlr frame). Two of them
+ have the minimum stack frame size (kernel and __sighndlr
+ frames) of 96 bytes, and there is another with a stack frame
+ of 160 bytes (the call_user_handler frame). The ucontext_t
+ structure is after this offset. */
+ regs_off = 96 + 96 + 160;
+ }
else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x9410001b)
/* This matches the call_user_handler pattern for Solaris 9 and
for Solaris 8 running inside Solaris Containers respectively.
@@ -389,7 +420,7 @@ sparc_fallback_frame_state (struct _Unwind_Context *context,
fpu_save_off = regs_off + (4*10) + (4*20);
/* The fpregs field contains 32 words at the beginning that contain
- the fpu state. Then there are 2 words and two bytes. */
+ the FPU state. Then there are 2 words and two bytes. */
fpu_save = *(unsigned char *)(this_cfa + fpu_save_off + (4*32) + (2*4) + 2);
/* We need to get the frame pointer for the kernel frame that
@@ -429,7 +460,7 @@ sparc_fallback_frame_state (struct _Unwind_Context *context,
fs->regs.reg[i + 16].loc.offset = i*4;
}
- /* Check whether we need to restore fpu registers. */
+ /* Check whether we need to restore FPU registers. */
if (fpu_save)
{
for (i = 0; i < 32; i++)
diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h
index e6fe4c0c969..d41bb80f4da 100644
--- a/gcc/config/stormy16/stormy16-protos.h
+++ b/gcc/config/stormy16/stormy16-protos.h
@@ -35,13 +35,6 @@ extern void xstormy16_asm_output_aligned_common (FILE *, tree, const char *,
int, int, int);
#endif
-#if defined (TREE_CODE) && defined (HAVE_MACHINE_MODES)
-extern CUMULATIVE_ARGS xstormy16_function_arg_advance
- (CUMULATIVE_ARGS, enum machine_mode, tree, int);
-extern rtx xstormy16_function_arg
- (CUMULATIVE_ARGS, enum machine_mode, tree, int);
-#endif
-
#if defined (TREE_CODE) && defined (RTX_CODE)
extern void xstormy16_initialize_trampoline (rtx, rtx, rtx);
extern rtx xstormy16_function_value (const_tree, const_tree);
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 7143c178f1c..e5bf08b45f2 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1247,11 +1247,10 @@ xstormy16_function_profiler (void)
sorry ("function_profiler support");
}
-/* Return an updated summarizer variable CUM to advance past an
- argument in the argument list. The values MODE, TYPE and NAMED
- describe that argument. Once this is done, the variable CUM is
- suitable for analyzing the *following* argument with
- `FUNCTION_ARG', etc.
+/* Update CUM to advance past an argument in the argument list. The
+ values MODE, TYPE and NAMED describe that argument. Once this is
+ done, the variable CUM is suitable for analyzing the *following*
+ argument with `TARGET_FUNCTION_ARG', etc.
This function need not do anything if the argument in question was
passed on the stack. The compiler knows how to track the amount of
@@ -1259,25 +1258,23 @@ xstormy16_function_profiler (void)
it makes life easier for xstormy16_build_va_list if it does update
the word count. */
-CUMULATIVE_ARGS
-xstormy16_function_arg_advance (CUMULATIVE_ARGS cum, enum machine_mode mode,
- tree type, int named ATTRIBUTE_UNUSED)
+static void
+xstormy16_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
{
/* If an argument would otherwise be passed partially in registers,
and partially on the stack, the whole of it is passed on the
stack. */
- if (cum < NUM_ARGUMENT_REGISTERS
- && cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS)
- cum = NUM_ARGUMENT_REGISTERS;
-
- cum += XSTORMY16_WORD_SIZE (type, mode);
+ if (*cum < NUM_ARGUMENT_REGISTERS
+ && *cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS)
+ *cum = NUM_ARGUMENT_REGISTERS;
- return cum;
+ *cum += XSTORMY16_WORD_SIZE (type, mode);
}
-rtx
-xstormy16_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
- tree type, int named ATTRIBUTE_UNUSED)
+static rtx
+xstormy16_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
{
if (mode == VOIDmode)
return const0_rtx;
@@ -2663,6 +2660,11 @@ static const struct default_options xstorym16_option_optimization_table[] =
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG xstormy16_function_arg
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE xstormy16_function_arg_advance
+
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY xstormy16_return_in_memory
diff --git a/gcc/config/stormy16/stormy16.h b/gcc/config/stormy16/stormy16.h
index 24402133e20..1ac73c41b9b 100644
--- a/gcc/config/stormy16/stormy16.h
+++ b/gcc/config/stormy16/stormy16.h
@@ -337,9 +337,6 @@ enum reg_class
+ 1) \
/ 2)
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- xstormy16_function_arg (CUM, MODE, TYPE, NAMED)
-
/* For this platform, the value of CUMULATIVE_ARGS is the number of words
of arguments that have been passed in registers so far. */
#define CUMULATIVE_ARGS int
@@ -347,9 +344,6 @@ enum reg_class
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
(CUM) = 0
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- ((CUM) = xstormy16_function_arg_advance (CUM, MODE, TYPE, NAMED))
-
#define FUNCTION_ARG_REGNO_P(REGNO) \
((REGNO) >= FIRST_ARGUMENT_REGISTER \
&& (REGNO) < FIRST_ARGUMENT_REGISTER + NUM_ARGUMENT_REGISTERS)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4a07a8aed92..822ed140bea 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,6 +1,32 @@
+2010-10-30 Nathan Froyd <froydnj@codesourcery.com>
+
+ * class.c (layout_vtable_decl): Call build_array_of_n_type.
+ (build_vtt, build_ctor_vtabl_group): Likewise.
+
+2010-10-30 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+ * parser.c (cp_parser_objc_at_property_declaration): Removed
+ parsing of RID_COPIES and RID_IVAR. Updated call to
+ objc_add_property_declaration.
+ * typecheck.c (finish_class_member_access_expr): Call
+ objc_maybe_build_component_ref instead of objc_build_setter_call.
+ (cp_build_modify_expr): Call objc_maybe_build_modify_expr instead
+ of objc_build_getter_call.
+
+2010-10-27 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (cp_trait_kind): Add CPTK_IS_LITERAL_TYPE.
+ * cxx-pretty-print.c (pp_cxx_trait_expression): Handle it.
+ * semantics.c (trait_expr_value, finish_trait_expr): Likewise.
+ * parser.c (cp_parser_primary_expression): Handle RID_IS_LITERAL_TYPE.
+ (cp_parser_trait_expr): Likewise.
+
2010-10-27 Gabriel Dos Reis <gdr@cse.tamu.edu>
Jason Merrill <jason@redhat.com>
+ * decl.c (finish_case_label): Use decl_constant_value.
+
* method.c (synthesized_method_walk): Track constexprness too.
(process_subob_fn, walk_field_subobs): Likewise.
(implicitly_declare_fn): Set DECL_DECLARED_CONSTEXPR_P.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a2c3ec37b3a..b683b21d0e2 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1858,8 +1858,7 @@ layout_vtable_decl (tree binfo, int n)
tree atype;
tree vtable;
- atype = build_cplus_array_type (vtable_entry_type,
- build_index_type (size_int (n - 1)));
+ atype = build_array_of_n_type (vtable_entry_type, n);
layout_type (atype);
/* We may have to grow the vtable. */
@@ -7295,8 +7294,8 @@ build_vtt (tree t)
return;
/* Figure out the type of the VTT. */
- type = build_index_type (size_int (VEC_length (constructor_elt, inits) - 1));
- type = build_cplus_array_type (const_ptr_type_node, type);
+ type = build_array_of_n_type (const_ptr_type_node,
+ VEC_length (constructor_elt, inits));
/* Now, build the VTT object itself. */
vtt = build_vtable (t, mangle_vtt_for_type (t), type);
@@ -7551,8 +7550,8 @@ build_ctor_vtbl_group (tree binfo, tree t)
}
/* Figure out the type of the construction vtable. */
- type = build_index_type (size_int (VEC_length (constructor_elt, v) - 1));
- type = build_cplus_array_type (vtable_entry_type, type);
+ type = build_array_of_n_type (vtable_entry_type,
+ VEC_length (constructor_elt, v));
layout_type (type);
TREE_TYPE (vtbl) = type;
DECL_SIZE (vtbl) = DECL_SIZE_UNIT (vtbl) = NULL_TREE;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 508e16128ff..cd8f1624815 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -22727,10 +22727,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
bool property_readwrite = false;
bool property_retain = false;
tree property_setter_ident = NULL_TREE;
- /* The following two will be removed once @synthesize is
- implemented. */
- bool property_copies = false;
- tree property_ivar_ident = NULL_TREE;
/* 'properties' is the list of properties that we read. Usually a
single one, but maybe more (eg, in "@property int a, b, c;" there
@@ -22764,7 +22760,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
switch (keyword)
{
case RID_ASSIGN: property_assign = true; break;
- case RID_COPIES: property_copies = true; break;
case RID_COPY: property_copy = true; break;
case RID_NONATOMIC: property_nonatomic = true; break;
case RID_READONLY: property_readonly = true; break;
@@ -22773,7 +22768,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
case RID_GETTER:
case RID_SETTER:
- case RID_IVAR:
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
{
cp_parser_error (parser,
@@ -22800,7 +22794,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
else
cp_lexer_consume_token (parser->lexer);
}
- else if (keyword == RID_GETTER)
+ else
{
if (property_getter_ident != NULL_TREE)
cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
@@ -22808,14 +22802,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
cp_lexer_consume_token (parser->lexer);
}
- else /* RID_IVAR, this case will go away. */
- {
- if (property_ivar_ident != NULL_TREE)
- cp_parser_error (parser, "the %<ivar%> attribute may only be specified once");
- else
- property_ivar_ident = cp_lexer_peek_token (parser->lexer)->u.value;
- cp_lexer_consume_token (parser->lexer);
- }
break;
default:
cp_parser_error (parser, "unknown property attribute");
@@ -22866,9 +22852,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
property_readonly, property_readwrite,
property_assign, property_retain,
property_copy, property_nonatomic,
- property_getter_ident, property_setter_ident,
- /* The following two will be removed. */
- property_copies, property_ivar_ident);
+ property_getter_ident, property_setter_ident);
}
cp_parser_consume_semicolon_at_end_of_statement (parser);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e0c73dc26f4..8ba874d404b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2598,7 +2598,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
}
else if (c_dialect_objc ()
&& TREE_CODE (name) == IDENTIFIER_NODE
- && (expr = objc_build_getter_call (object, name)))
+ && (expr = objc_maybe_build_component_ref (object, name)))
return expr;
/* [expr.ref]
@@ -6767,7 +6767,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
{
if (c_dialect_objc ())
{
- result = objc_build_setter_call (lhs, rhs);
+ result = objc_maybe_build_modify_expr (lhs, rhs);
if (result)
return result;
}
@@ -6812,7 +6812,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
modifycode = NOP_EXPR;
if (c_dialect_objc ())
{
- result = objc_build_setter_call (lhs, newrhs);
+ result = objc_maybe_build_modify_expr (lhs, newrhs);
if (result)
return result;
}
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index c37e4b38489..de2be889bdc 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -6315,6 +6315,24 @@ minus or complement operators on a vector type is a vector whose
elements are the negative or complemented values of the corresponding
elements in the operand.
+In C it is possible to use shifting operators @code{<<}, @code{>>} on
+integer-type vectors. The operation is defined as following: @code{@{a0,
+a1, @dots{}, an@} >> @{b0, b1, @dots{}, bn@} == @{a0 >> b0, a1 >> b1,
+@dots{}, an >> bn@}}@. Vector operands must have the same number of
+elements. Additionally second operands can be a scalar integer in which
+case the scalar is converted to the type used by the vector operand (with
+possible truncation) and each element of this new vector is the scalar's
+value.
+Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b;
+
+b = a >> 1; /* b = a >> @{1,1,1,1@}; */
+@end smallexample
+
In C vectors can be subscripted as if the vector were an array with
the same number of elements and base type. Out of bound accesses
invoke undefined behavior at runtime. Warnings for out of bound
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 365b8c3af43..4a605e315c3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -734,8 +734,8 @@ Objective-C and Objective-C++ Dialects}.
@emph{MN10300 Options}
@gccoptlist{-mmult-bug -mno-mult-bug @gol
--mam33 -mno-am33 @gol
--mam33-2 -mno-am33-2 @gol
+-mno-am33 -mam33 -mam33-2 -mam34 @gol
+-mtune=@var{cpu-type} @gol
-mreturn-pointer-on-d0 @gol
-mno-crt0 -mrelax}
@@ -14915,6 +14915,21 @@ Generate code which uses features specific to the AM33 processor.
Do not generate code which uses features specific to the AM33 processor. This
is the default.
+@item -mam33-2
+@opindex mam33-2
+Generate code which uses features specific to the AM33/2.0 processor.
+
+@item -mam34
+@opindex mam34
+Generate code which uses features specific to the AM34 processor.
+
+@item -mtune=@var{cpu-type}
+@opindex mtune
+Use the timing characteristics of the indicated CPU type when
+scheduling instructions. This does not change the targeted processor
+type. The CPU type must be one of @samp{mn10300}, @samp{am33},
+@samp{am33-2} or @samp{am34}.
+
@item -mreturn-pointer-on-d0
@opindex mreturn-pointer-on-d0
When generating a function which returns a pointer, return the pointer
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 66a092fbc1a..0c2db4739d0 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -2486,17 +2486,6 @@ added to another register (as well as added to a displacement).
@defmac REGNO_OK_FOR_BASE_P (@var{num})
A C expression which is nonzero if register number @var{num} is
suitable for use as a base register in operand addresses.
-Like @code{TARGET_LEGITIMATE_ADDRESS_P}, this macro should also
-define a strict and a non-strict variant. Both variants behave
-the same for hard register; for pseudos, the strict variant will
-pass only those that have been allocated to a valid hard registers,
-while the non-strict variant will pass all pseudos.
-
-@findex REG_OK_STRICT
-Compiler source files that want to use the strict variant of this and
-other macros define the macro @code{REG_OK_STRICT}. You should use an
-@code{#ifdef REG_OK_STRICT} conditional to define the strict variant in
-that case and the non-strict variant otherwise.
@end defmac
@defmac REGNO_MODE_OK_FOR_BASE_P (@var{num}, @var{mode})
@@ -2508,8 +2497,6 @@ you define this macro, the compiler will use it instead of
@code{REGNO_OK_FOR_BASE_P}. The mode may be @code{VOIDmode} for
addresses that appear outside a @code{MEM}, i.e., as an
@code{address_operand}.
-
-This macro also has strict and non-strict variants.
@end defmac
@defmac REGNO_MODE_OK_FOR_REG_BASE_P (@var{num}, @var{mode})
@@ -2522,8 +2509,6 @@ than other base register uses.
Use of this macro is deprecated; please use the more general
@code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
-
-This macro also has strict and non-strict variants.
@end defmac
@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{outer_code}, @var{index_code})
@@ -2536,8 +2521,6 @@ address, @code{ADDRESS} for something that occurs in an
corresponding index expression if @var{outer_code} is @code{PLUS};
@code{SCRATCH} otherwise. The mode may be @code{VOIDmode} for addresses
that appear outside a @code{MEM}, i.e., as an @code{address_operand}.
-
-This macro also has strict and non-strict variants.
@end defmac
@defmac REGNO_OK_FOR_INDEX_P (@var{num})
@@ -2554,8 +2537,6 @@ labeling is used must fit the machine's constraints of which registers
may serve in each capacity. The compiler will try both labelings,
looking for one that is valid, and will reload one or both registers
only if neither labeling works.
-
-This macro also has strict and non-strict variants.
@end defmac
@deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RELOAD_CLASS (rtx @var{x}, reg_class_t @var{rclass})
@@ -4606,6 +4587,14 @@ This macro has effect in @option{-fpcc-struct-return} mode, but it does
nothing when you use @option{-freg-struct-return} mode.
@end defmac
+@deftypefn {Target Hook} {enum machine_mode} TARGET_GET_RAW_RESULT_MODE (int @var{regno})
+This target hook returns the mode to be used when accessing raw return registers in @code{__builtin_return}. Define this macro if the value in @var{reg_raw_mode} is not correct.
+@end deftypefn
+
+@deftypefn {Target Hook} {enum machine_mode} TARGET_GET_RAW_ARG_MODE (int @var{regno})
+This target hook returns the mode to be used when accessing raw argument registers in @code{__builtin_apply_args}. Define this macro if the value in @var{reg_raw_mode} is not correct.
+@end deftypefn
+
@node Caller Saves
@subsection Caller-Saves Register Allocation
@@ -5485,8 +5474,13 @@ has this syntax:
@noindent
and should @code{goto @var{label}} if the address @var{x} is a valid
address on the target machine for a memory operand of mode @var{mode}.
-Whether the strict or non-strict variants are desired is defined by
-the @code{REG_OK_STRICT} macro introduced earlier in this section.
+
+@findex REG_OK_STRICT
+Compiler source files that want to use the strict variant of this
+macro define the macro @code{REG_OK_STRICT}. You should use an
+@code{#ifdef REG_OK_STRICT} conditional to define the strict variant in
+that case and the non-strict variant otherwise.
+
Using the hook is usually simpler because it limits the number of
files that are recompiled when changes are made.
@end deftypefn
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index a5fb0007920..c4d5e8ab150 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -2480,17 +2480,6 @@ added to another register (as well as added to a displacement).
@defmac REGNO_OK_FOR_BASE_P (@var{num})
A C expression which is nonzero if register number @var{num} is
suitable for use as a base register in operand addresses.
-Like @code{TARGET_LEGITIMATE_ADDRESS_P}, this macro should also
-define a strict and a non-strict variant. Both variants behave
-the same for hard register; for pseudos, the strict variant will
-pass only those that have been allocated to a valid hard registers,
-while the non-strict variant will pass all pseudos.
-
-@findex REG_OK_STRICT
-Compiler source files that want to use the strict variant of this and
-other macros define the macro @code{REG_OK_STRICT}. You should use an
-@code{#ifdef REG_OK_STRICT} conditional to define the strict variant in
-that case and the non-strict variant otherwise.
@end defmac
@defmac REGNO_MODE_OK_FOR_BASE_P (@var{num}, @var{mode})
@@ -2502,8 +2491,6 @@ you define this macro, the compiler will use it instead of
@code{REGNO_OK_FOR_BASE_P}. The mode may be @code{VOIDmode} for
addresses that appear outside a @code{MEM}, i.e., as an
@code{address_operand}.
-
-This macro also has strict and non-strict variants.
@end defmac
@defmac REGNO_MODE_OK_FOR_REG_BASE_P (@var{num}, @var{mode})
@@ -2516,8 +2503,6 @@ than other base register uses.
Use of this macro is deprecated; please use the more general
@code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
-
-This macro also has strict and non-strict variants.
@end defmac
@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{outer_code}, @var{index_code})
@@ -2530,8 +2515,6 @@ address, @code{ADDRESS} for something that occurs in an
corresponding index expression if @var{outer_code} is @code{PLUS};
@code{SCRATCH} otherwise. The mode may be @code{VOIDmode} for addresses
that appear outside a @code{MEM}, i.e., as an @code{address_operand}.
-
-This macro also has strict and non-strict variants.
@end defmac
@defmac REGNO_OK_FOR_INDEX_P (@var{num})
@@ -2548,8 +2531,6 @@ labeling is used must fit the machine's constraints of which registers
may serve in each capacity. The compiler will try both labelings,
looking for one that is valid, and will reload one or both registers
only if neither labeling works.
-
-This macro also has strict and non-strict variants.
@end defmac
@hook TARGET_PREFERRED_RELOAD_CLASS
@@ -4600,6 +4581,10 @@ This macro has effect in @option{-fpcc-struct-return} mode, but it does
nothing when you use @option{-freg-struct-return} mode.
@end defmac
+@hook TARGET_GET_RAW_RESULT_MODE
+
+@hook TARGET_GET_RAW_ARG_MODE
+
@node Caller Saves
@subsection Caller-Saves Register Allocation
@@ -5477,8 +5462,13 @@ has this syntax:
@noindent
and should @code{goto @var{label}} if the address @var{x} is a valid
address on the target machine for a memory operand of mode @var{mode}.
-Whether the strict or non-strict variants are desired is defined by
-the @code{REG_OK_STRICT} macro introduced earlier in this section.
+
+@findex REG_OK_STRICT
+Compiler source files that want to use the strict variant of this
+macro define the macro @code{REG_OK_STRICT}. You should use an
+@code{#ifdef REG_OK_STRICT} conditional to define the strict variant in
+that case and the non-strict variant otherwise.
+
Using the hook is usually simpler because it limits the number of
files that are recompiled when changes are made.
@end deftypefn
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 19d290c4b2c..eb4ea2a97d8 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -2728,11 +2728,10 @@ repeat:
return;
}
-/* Clear all the USED bits in X to allow copy_rtx_if_shared to be used
- to look for shared sub-parts. */
+/* Set the USED bit in X and its non-shareable subparts to FLAG. */
-void
-reset_used_flags (rtx x)
+static void
+mark_used_flags (rtx x, int flag)
{
int i, j;
enum rtx_code code;
@@ -2778,7 +2777,7 @@ repeat:
break;
}
- RTX_FLAG (x, used) = 0;
+ RTX_FLAG (x, used) = flag;
format_ptr = GET_RTX_FORMAT (code);
length = GET_RTX_LENGTH (code);
@@ -2793,81 +2792,33 @@ repeat:
x = XEXP (x, i);
goto repeat;
}
- reset_used_flags (XEXP (x, i));
+ mark_used_flags (XEXP (x, i), flag);
break;
case 'E':
for (j = 0; j < XVECLEN (x, i); j++)
- reset_used_flags (XVECEXP (x, i, j));
+ mark_used_flags (XVECEXP (x, i, j), flag);
break;
}
}
}
-/* Set all the USED bits in X to allow copy_rtx_if_shared to be used
+/* Clear all the USED bits in X to allow copy_rtx_if_shared to be used
to look for shared sub-parts. */
void
-set_used_flags (rtx x)
+reset_used_flags (rtx x)
{
- int i, j;
- enum rtx_code code;
- const char *format_ptr;
-
- if (x == 0)
- return;
-
- code = GET_CODE (x);
-
- /* These types may be freely shared so we needn't do any resetting
- for them. */
-
- switch (code)
- {
- case REG:
- case DEBUG_EXPR:
- case VALUE:
- case CONST_INT:
- case CONST_DOUBLE:
- case CONST_FIXED:
- case CONST_VECTOR:
- case SYMBOL_REF:
- case CODE_LABEL:
- case PC:
- case CC0:
- return;
-
- case DEBUG_INSN:
- case INSN:
- case JUMP_INSN:
- case CALL_INSN:
- case NOTE:
- case LABEL_REF:
- case BARRIER:
- /* The chain of insns is not being copied. */
- return;
-
- default:
- break;
- }
-
- RTX_FLAG (x, used) = 1;
+ mark_used_flags (x, 0);
+}
- format_ptr = GET_RTX_FORMAT (code);
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- {
- switch (*format_ptr++)
- {
- case 'e':
- set_used_flags (XEXP (x, i));
- break;
+/* Set all the USED bits in X to allow copy_rtx_if_shared to be used
+ to look for shared sub-parts. */
- case 'E':
- for (j = 0; j < XVECLEN (x, i); j++)
- set_used_flags (XVECEXP (x, i, j));
- break;
- }
- }
+void
+set_used_flags (rtx x)
+{
+ mark_used_flags (x, 1);
}
/* Copy X if necessary so that it won't be altered by changes in OTHER.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index accb35cf1cb..d29e1a10103 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1796,16 +1796,10 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
static tree
build_zero_vector (tree type)
{
- tree elem, list;
- int i, units;
-
- elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
- units = TYPE_VECTOR_SUBPARTS (type);
+ tree t;
- list = NULL_TREE;
- for (i = 0; i < units; i++)
- list = tree_cons (NULL_TREE, elem, list);
- return build_vector (type, list);
+ t = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+ return build_vector_from_val (type, t);
}
/* Returns true, if ARG is convertible to TYPE using a NOP_EXPR. */
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index c4c3608a76d..9dae56aebe5 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,41 @@
+2010-10-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * gfortran.h (gfc_option_t): Replace dump_parse_tree by
+ dump_fortran_original and add dump_fortran_optimized.
+ * lang.opt: Add fdump-fortran-original and
+ fdump-fortran-optimized. Document that fdump-parse-tree is
+ deprecated.
+ * gfortran.texi: Add -fdump-fortran-original and
+ -fdump-fortran-optimized. -fdump-parse-tree is deprecated.
+ * frontend-passes.c (gfc_run_passes): If optimizing and
+ if gfc_option.dump_fortran_optimized is set, dump the parse tree
+ after optimization.
+ * parse.c: Rename gfc_option.dump_parse_tree to
+ gfc_option.dump_fortran_original.
+ * options.c (gfc_init_options): Rename gfc_option.dump_parse_tree
+ to gfc_option.dump_fortran_original and handle
+ gfc_option.dump_fortran_optimize.
+ (gfc_post_options): Rename gfc_option.dump_parse_tree
+ to gfc_option.dump_fortran_original.
+ (gfc_handle_option): Rename OPT_fdump_parse_tree to
+ OPT_fdump_fortran_original and gfc_option.dump_parse_tree
+ to gfc_option.dump_fortran_original. Handle
+ OPT_fdump_fortran_optimized.
+
+2010-10-30 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44917
+ PR fortran/44926
+ PR fortran/46196
+ * interface.c (count_types_test): Symmetrize type check.
+ (generic_correspondence): Ditto.
+
+2010-10-27 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/46161
+ * interface.c (compare_allocatable): Handle polymorphic allocatables.
+ (compare_parameter): Add two error messages for polymorphic dummies.
+
2010-10-26 Janus Weil <janus@gcc.gnu.org>
PR fortran/42647
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index c08930297e1..6cea263bdee 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -42,7 +42,11 @@ void
gfc_run_passes (gfc_namespace *ns)
{
if (optimize)
- optimize_namespace (ns);
+ {
+ optimize_namespace (ns);
+ if (gfc_option.dump_fortran_optimized)
+ gfc_dump_parse_tree (ns, stdout);
+ }
}
/* Callback for each gfc_code node invoked through gfc_code_walker
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 33c7ba6e1a5..b96dd6420ca 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2178,7 +2178,8 @@ typedef struct
int max_continue_fixed;
int max_continue_free;
int max_identifier_length;
- int dump_parse_tree;
+ int dump_fortran_original;
+ int dump_fortran_optimized;
int warn_aliasing;
int warn_ampersand;
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 6ae36c2fb6a..cf83557be55 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -872,7 +872,8 @@ count_types_test (gfc_formal_arglist *f1, gfc_formal_arglist *f2)
/* Find other nonoptional arguments of the same type/rank. */
for (j = i + 1; j < n1; j++)
if ((arg[j].sym == NULL || !arg[j].sym->attr.optional)
- && compare_type_rank_if (arg[i].sym, arg[j].sym))
+ && (compare_type_rank_if (arg[i].sym, arg[j].sym)
+ || compare_type_rank_if (arg[j].sym, arg[i].sym)))
arg[j].flag = k;
k++;
@@ -897,7 +898,8 @@ count_types_test (gfc_formal_arglist *f1, gfc_formal_arglist *f2)
ac2 = 0;
for (f = f2; f; f = f->next)
- if (compare_type_rank_if (arg[i].sym, f->sym))
+ if (compare_type_rank_if (arg[i].sym, f->sym)
+ || compare_type_rank_if (f->sym, arg[i].sym))
ac2++;
if (ac1 > ac2)
@@ -948,7 +950,8 @@ generic_correspondence (gfc_formal_arglist *f1, gfc_formal_arglist *f2)
if (f1->sym->attr.optional)
goto next;
- if (f2 != NULL && compare_type_rank (f1->sym, f2->sym))
+ if (f2 != NULL && (compare_type_rank (f1->sym, f2->sym)
+ || compare_type_rank (f2->sym, f1->sym)))
goto next;
/* Now search for a disambiguating keyword argument starting at
@@ -1375,7 +1378,8 @@ compare_allocatable (gfc_symbol *formal, gfc_expr *actual)
{
symbol_attribute attr;
- if (formal->attr.allocatable)
+ if (formal->attr.allocatable
+ || (formal->ts.type == BT_CLASS && CLASS_DATA (formal)->attr.allocatable))
{
attr = gfc_expr_attr (actual);
if (!attr.allocatable)
@@ -1519,6 +1523,28 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
gfc_typename (&formal->ts));
return 0;
}
+
+ /* F2003, 12.5.2.5. */
+ if (formal->ts.type == BT_CLASS
+ && (CLASS_DATA (formal)->attr.class_pointer
+ || CLASS_DATA (formal)->attr.allocatable))
+ {
+ if (actual->ts.type != BT_CLASS)
+ {
+ if (where)
+ gfc_error ("Actual argument to '%s' at %L must be polymorphic",
+ formal->name, &actual->where);
+ return 0;
+ }
+ if (CLASS_DATA (actual)->ts.u.derived
+ != CLASS_DATA (formal)->ts.u.derived)
+ {
+ if (where)
+ gfc_error ("Actual argument to '%s' at %L must have the same "
+ "declared type", formal->name, &actual->where);
+ return 0;
+ }
+ }
if (formal->attr.codimension)
{
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 9e2bc758d37..bacab6ba6bf 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -143,8 +143,8 @@ and warnings}.
@item Debugging Options
@xref{Debugging Options,,Options for debugging your program or GNU Fortran}.
-@gccoptlist{-fdump-parse-tree -ffpe-trap=@var{list} @gol
--fdump-core -fbacktrace}
+@gccoptlist{-fdump-fortran-original -fdump-fortran-optimized @gol
+-ffpe-trap=@var{list} -fdump-core -fbacktrace -fdump-parse-tree}
@item Directory Options
@xref{Directory Options,,Options for directory search}.
@@ -879,10 +879,22 @@ GNU Fortran has various special options that are used for debugging
either your program or the GNU Fortran compiler.
@table @gcctabopt
-@item -fdump-parse-tree
+@item -fdump-fortran-original
+@opindex @code{fdump-fortran-original}
+Output the internal parse tree after translating the source program
+into internal representation. Only really useful for debugging the
+GNU Fortran compiler itself.
+
+@item -fdump-optimized-tree
+@opindex @code{fdump-fortran-optimized}
+Output the parse tree after front-end optimization. Only really
+useful for debugging the GNU Fortran compiler itself.
+
@opindex @code{fdump-parse-tree}
-Output the internal parse tree before starting code generation. Only
-really useful for debugging the GNU Fortran compiler itself.
+Output the internal parse tree after translating the source program
+into internal representation. Only really useful for debugging the
+GNU Fortran compiler itself. This option is deprecated; use
+@code{-fdump-fortran-original} instead.
@item -ffpe-trap=@var{list}
@opindex @code{ffpe-trap=}@var{list}
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index f60eaabea8b..60887300340 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -358,10 +358,18 @@ fdump-core
Fortran
Dump a core file when a runtime error occurs
-fdump-parse-tree
+fdump-fortran-original
Fortran
Display the code tree after parsing
+fdump-fortran-optimized
+Fortran
+Display the code tree after front end optimization
+
+fdump-parse-tree
+Fortran
+Display the code tree after parsing; deprecated option
+
fexternal-blas
Fortran
Specify that an external BLAS library should be used for matmul calls on large-size arrays
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index a65a63ab48c..36dd9c83115 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -90,7 +90,8 @@ gfc_init_options (unsigned int decoded_options_count,
gfc_option.flag_max_array_constructor = 65535;
gfc_option.convert = GFC_CONVERT_NATIVE;
gfc_option.record_marker = 0;
- gfc_option.dump_parse_tree = 0;
+ gfc_option.dump_fortran_original = 0;
+ gfc_option.dump_fortran_optimized = 0;
gfc_option.warn_aliasing = 0;
gfc_option.warn_ampersand = 0;
@@ -270,7 +271,7 @@ gfc_post_options (const char **pfilename)
gfc_option.rtcheck |= GFC_RTCHECK_BOUNDS;
if (flag_compare_debug)
- gfc_option.dump_parse_tree = 0;
+ gfc_option.dump_fortran_original = 0;
/* Verify the input file name. */
if (!filename || strcmp (filename, "-") == 0)
@@ -686,8 +687,13 @@ gfc_handle_option (size_t scode, const char *arg, int value,
gfc_option.flag_d_lines = 0;
break;
+ case OPT_fdump_fortran_original:
case OPT_fdump_parse_tree:
- gfc_option.dump_parse_tree = value;
+ gfc_option.dump_fortran_original = value;
+ break;
+
+ case OPT_fdump_fortran_optimized:
+ gfc_option.dump_fortran_optimized = value;
break;
case OPT_ffixed_form:
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 89ffbafa96c..2e438245646 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -4373,7 +4373,7 @@ loop:
gfc_resolve (gfc_current_ns);
/* Dump the parse tree if requested. */
- if (gfc_option.dump_parse_tree)
+ if (gfc_option.dump_fortran_original)
gfc_dump_parse_tree (gfc_current_ns, stdout);
gfc_get_errors (NULL, &errors);
@@ -4431,7 +4431,7 @@ prog_units:
/* Do the parse tree dump. */
gfc_current_ns
- = gfc_option.dump_parse_tree ? gfc_global_ns_list : NULL;
+ = gfc_option.dump_fortran_original ? gfc_global_ns_list : NULL;
for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
{
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index 71729af1fe0..1c4e9adb004 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -396,7 +396,7 @@ simplify_subreg_concatn (enum machine_mode outermode, rtx op,
unsigned int byte)
{
unsigned int inner_size;
- enum machine_mode innermode;
+ enum machine_mode innermode, partmode;
rtx part;
unsigned int final_offset;
@@ -409,11 +409,19 @@ simplify_subreg_concatn (enum machine_mode outermode, rtx op,
inner_size = GET_MODE_SIZE (innermode) / XVECLEN (op, 0);
part = XVECEXP (op, 0, byte / inner_size);
+ partmode = GET_MODE (part);
+
+ if (partmode == VOIDmode)
+ {
+ gcc_assert (VECTOR_MODE_P (innermode));
+ partmode = GET_MODE_INNER (innermode);
+ }
+
final_offset = byte % inner_size;
if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
return NULL_RTX;
- return simplify_gen_subreg (outermode, part, GET_MODE (part), final_offset);
+ return simplify_gen_subreg (outermode, part, partmode, final_offset);
}
/* Wrapper around simplify_gen_subreg which handles CONCATN. */
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index aa5876489a5..04841334ff9 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,94 @@
+2010-10-30 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+ * objc-tree.def (PROPERTY_REF): New.
+ * objc-act.h: Added comments for all the PROPERTY_ macros.
+ (PROPERTY_NAME): Use DECL_NAME.
+ (PROPERTY_COPIES): Removed.
+ (PROPERTY_READONLY): Use DECL_LANG_FLAG_0 for it.
+ (PROPERTY_NONATOMIC): New.
+ (objc_property_assign_semantics): Make it a typedef.
+ (PROPERTY_ASSIGN_SEMANTICS): New.
+ (PROPERTY_DYNAMIC): New.
+ (PROPERTY_REF_OBJECT): New.
+ (PROPERTY_REF_PROPERTY_DECL): New.
+ * objc-act.c (CALL_EXPR_OBJC_PROPERTY_GETTER): Removed.
+ (in_objc_property_setter_name_context): Removed.
+ (objc_add_property_declaration): Removed copies and ivar arguments
+ and code supporting them. Fixed recovering when readonly and
+ setter attributes are specified. Removed support for @property in
+ @implementation context. Updated error message. Double-check
+ that a property does not have a DECL_INITIAL. Validate the
+ property assign semantics and emit appropriate errors and
+ warnings. Check for duplicate property declarations. Set
+ DECL_SOURCE_LOCATION, TREE_DEPRECATED, PROPERTY_NONATOMIC,
+ PROPERTY_ASSIGN_SEMANTICS and PROPERTY_DYNAMIC of the new
+ PROPERTY_DECL. Do not set PROPERTY_COPIES. Set
+ PROPERTY_IVAR_NAME to NULL_TREE.
+ (objc_build_getter_call): Renamed to
+ objc_maybe_build_component_ref. If the property is not found in
+ the interface, search in the protocol list. Do not generate the
+ getter call; instead, build and return a PROPERTY_REF.
+ (objc_is_property_ref): New.
+ (objc_setter_func_call): Removed.
+ (get_selector_from_reference): Removed.
+ (is_property): Removed.
+ (objc_build_setter_call): Renamed to objc_maybe_build_modify_expr.
+ Updated to work on a PROPERTY_REF and use the PROPERTY_DECL from
+ the PROPERTY_REF. Generate an error if the property is read-only.
+ (build_property_reference): Removed.
+ (objc_finish_message_expr): Removed check to produce "readonly
+ property can not be set" error when
+ in_objc_property_setter_name_context. We now generate the error
+ earlier, in objc_maybe_build_modify_expr, which will only generate
+ the setter call if the property is readwrite.
+ (check_methods): Recognize dynamic properties.
+ (check_methods_accessible): Same change.
+ (objc_build_property_ivar_name): Removed.
+ (objc_build_property_setter_name): Dropped bool argument. Always
+ add the ':' at the end.
+ (objc_gen_one_property_datum): Removed.
+ (objc_process_getter_setter): Removed.
+ (objc_synthesize_getter): Mark 'klass' argument as unused. Use
+ PROPERTY_GETTER_NAME instead of PROPERTY_NAME. Set the
+ DECL_SOURCE_LOCATION of the new method to be the same as the one
+ for the @synthesize. Always use PROPERTY_IVAR_NAME as it is
+ instead of trying to guess what it should be. Removed use of
+ CLASS_IVARS. Use the location of @synthesize for c_finish_return
+ and c_end_compound_statement.
+ (objc_synthesize_setter): Mark 'klass' argument as unused. Use
+ PROPERTY_SETTER_NAME instead of trying to guess what it should be.
+ Set the DECL_SOURCE_LOCATION of the new method to be the same as
+ the one for the @synthesize. Always use PROPERTY_IVAR_NAME as it
+ is instead of trying to guess what it should be. Removed use of
+ CLASS_IVARS. Use the location of @synthesize for c_finish_return
+ and c_end_compound_statement. Emit an error and keep going,
+ instead of aborting, if the setter prototype does not have the
+ expected argument.
+ (objc_add_synthesize_declaration_for_property): New.
+ (objc_add_synthesize_declaration): Removed ATTRIBUTE_UNUSED from
+ all arguments. Improved error message. Filled in the rest of the
+ function, which used to be a placeholder, with an actual
+ implementation.
+ (objc_add_dynamic_declaration_for_property): New.
+ (objc_add_dynamic_declaration): Removed ATTRIBUTE_UNUSED from all
+ arguments. Improved error message. Filled in the rest of the
+ function, which used to be a placeholder, with an actual
+ implementation.
+ (objc_gen_property_data): Rewritten.
+ (finish_class): Added explicit switch cases for
+ CLASS_INTERFACE_TYPE, CATEGORY_INTERFACE_TYPE and
+ PROTOCOL_INTERFACE_TYPE. Added a default switch case which is
+ gcc_unreachable. Rewritten the processing of properties, in
+ particular to not synthesize prototypes for getters and setters if
+ they already exist and to install the getter and setter names into
+ PROPERTY_GETTER_NAME and PROPERTY_SETTER_NAME. Do not generate
+ warnings about setter, getter and ivar property attributes.
+ (objc_lookup_ivar): Removed support for properties.
+ (objc_gimplify_property_ref): New.
+ (objc_gimplify_expr): Use a switch. In case of a PROPERTY_REF, call
+ objc_gimplify_property_ref.
+
2010-10-27 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (objc_add_property_declaration): Added arguments to
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 674b77e6894..e564da55fbc 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -170,24 +170,14 @@ static bool objc_derived_from_p (tree, tree);
#endif
/* Property. */
-static void objc_gen_one_property_datum (tree, tree, tree, bool*);
static void objc_gen_property_data (tree, tree);
static void objc_synthesize_getter (tree, tree, tree);
-static void objc_process_getter_setter (tree, tree, bool);
static void objc_synthesize_setter (tree, tree, tree);
-static char *objc_build_property_ivar_name (tree);
-static char *objc_build_property_setter_name (tree, bool);
+static char *objc_build_property_setter_name (tree);
static int match_proto_with_proto (tree, tree, int);
static tree lookup_property (tree, tree);
static tree lookup_property_in_list (tree, tree);
static tree lookup_property_in_protocol_list (tree, tree);
-static tree objc_setter_func_call (tree, tree, tree);
-static tree build_property_reference (tree, tree);
-static tree is_property (tree, tree);
-/* Set on a CALL_EXPR if it is for call to a getter function represented by an
- objective-c property declaration. */
-#define CALL_EXPR_OBJC_PROPERTY_GETTER(NODE) \
- (CALL_EXPR_CHECK(NODE)->base.deprecated_flag)
static void objc_xref_basetypes (tree, tree);
@@ -406,8 +396,6 @@ static int method_slot = 0;
required. */
static bool objc_method_optional_flag = false;
-static bool in_objc_property_setter_name_context = false;
-
static int objc_collecting_ivars = 0;
#define BUFSIZE 1024
@@ -825,20 +813,18 @@ objc_add_property_declaration (location_t location, tree decl,
bool parsed_property_readonly, bool parsed_property_readwrite,
bool parsed_property_assign, bool parsed_property_retain,
bool parsed_property_copy, bool parsed_property_nonatomic,
- tree parsed_property_getter_ident, tree parsed_property_setter_ident,
- /* The following two will be removed. */
- bool parsed_property_copies, tree parsed_property_ivar_ident)
+ tree parsed_property_getter_ident, tree parsed_property_setter_ident)
{
tree property_decl;
tree x;
- tree interface = NULL_TREE;
- /* 'property_readonly' is the final readonly/rewrite attribute of
- the property declaration after all things have been
- considered. */
+ /* 'property_readonly' and 'property_assign_semantics' are the final
+ attributes of the property after all parsed attributes have been
+ considered (eg, if we parsed no 'readonly' and no 'readwrite', ie
+ parsed_property_readonly = false and parsed_property_readwrite =
+ false, then property_readonly will be false because the default
+ is readwrite). */
bool property_readonly = false;
- enum objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
- /* The following will be removed once @synthesize is implemented. */
- bool property_copies = false;
+ objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
if (parsed_property_readonly && parsed_property_readwrite)
{
@@ -859,9 +845,9 @@ objc_add_property_declaration (location_t location, tree decl,
if (parsed_property_readonly && parsed_property_setter_ident)
{
- /* Maybe this should be an error ? */
+ /* Maybe this should be an error ? The Apple documentation says it is a warning. */
warning_at (location, 0, "%<readonly%> attribute conflicts with %<setter%> attribute");
- parsed_property_readonly = false;
+ property_readonly = false;
}
if (parsed_property_assign && parsed_property_retain)
@@ -891,50 +877,19 @@ objc_add_property_declaration (location_t location, tree decl,
property_assign_semantics = OBJC_PROPERTY_COPY;
}
- /* This will be removed when @synthesize is implemented. */
- if (parsed_property_copies)
- property_copies = true;
-
- /* This case will be removed when @synthesize is implemented; then
- @property will only be allowed in an @interface context. */
- if (objc_implementation_context)
- {
- interface = lookup_interface (CLASS_NAME (objc_implementation_context));
- if (!interface)
- {
- error_at (location, "no class property can be implemented without an interface");
- return;
- }
- if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
- {
- interface = lookup_category (interface,
- CLASS_SUPER_NAME (objc_implementation_context));
- if (!interface)
- {
- error_at (location, "no category property can be implemented without an interface");
- return;
- }
- }
- }
- else if (objc_interface_context)
- {
- /* This will be removed when ivar is removed. */
- if (parsed_property_ivar_ident)
- {
- warning_at (location, 0, "the %<ivar%> attribute is ignored in an @interface");
- parsed_property_ivar_ident = NULL_TREE;
- }
- }
- else if (!objc_interface_context)
+ if (!objc_interface_context)
{
- error_at (location, "property declaration not in @interface or @implementation context");
+ error_at (location, "property declaration not in @interface or @protocol context");
return;
}
+ /* At this point we know that we are either in an interface, a
+ category, or a protocol. */
+
if (parsed_property_setter_ident)
{
/* The setter should be terminated by ':', but the parser only
- passes us an identifier without ':'. So, we need to add ':'
+ gives us an identifier without ':'. So, we need to add ':'
at the end. */
const char *parsed_setter = IDENTIFIER_POINTER (parsed_property_setter_ident);
size_t length = strlen (parsed_setter);
@@ -944,97 +899,98 @@ objc_add_property_declaration (location_t location, tree decl,
parsed_property_setter_ident = get_identifier (final_setter);
}
- property_decl = make_node (PROPERTY_DECL);
- TREE_TYPE (property_decl) = TREE_TYPE (decl);
+ /* Check that the property does not have an initial value specified.
+ This should never happen as the parser doesn't allow this, but
+ it's just in case. */
+ if (DECL_INITIAL (decl))
+ {
+ error_at (location, "property can not have an initial value");
+ return;
+ }
- PROPERTY_NAME (property_decl) = DECL_NAME (decl);
- PROPERTY_GETTER_NAME (property_decl) = parsed_property_getter_ident;
- PROPERTY_SETTER_NAME (property_decl) = parsed_property_setter_ident;
- PROPERTY_IVAR_NAME (property_decl) = parsed_property_ivar_ident;
- PROPERTY_READONLY (property_decl) = property_readonly
- ? boolean_true_node
- : boolean_false_node;
- PROPERTY_COPIES (property_decl) = property_copies
- ? boolean_true_node
- : boolean_false_node;
-
- /* TODO: The following is temporary code that will be removed when
- property_assign_semantics and property_nonatomic are
- implemented. */
- if (objc_implementation_context && objc_interface_context)
- {
- /* This branch is impossible but the compiler can't know it. Do
- something with property_assign_semantics and
- parsed_property_nonatomic (not implemented yet) to convince
- the compiler we're using them and prevent it from generating
- warnings and breaking bootstrap. */
- PROPERTY_COPIES (property_decl) = property_assign_semantics ? boolean_true_node : boolean_false_node;
- PROPERTY_READONLY (property_decl) = parsed_property_nonatomic ? boolean_true_node : boolean_false_node;
- }
-
- if (objc_interface_context)
- {
- /* Doing the property in interface declaration. */
-
- /* Issue error if property and an ivar name match. */
- if (TREE_CODE (objc_interface_context) == CLASS_INTERFACE_TYPE
- && is_ivar (CLASS_IVARS (objc_interface_context), DECL_NAME (decl)))
- error_at (location, "property %qD may not have the same name as an ivar in the class", decl);
- /* must check for duplicate property declarations. */
- for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
+ /* TODO: Check that the property type is an Objective-C object or a "POD". */
+
+ if (property_assign_semantics == OBJC_PROPERTY_ASSIGN)
+ {
+ /* If garbage collection is not being used, then 'assign' is
+ valid for objects (and typically used for delegates) but it
+ is wrong in most cases (since most objects need to be
+ retained or copied in setters). Warn users when 'assign' is
+ used implicitly. */
+ /* Please note that it would make sense to default to 'assign'
+ for non-{Objective-C objects}, and to 'retain' for
+ Objective-C objects. But that would break compatibility with
+ other compilers. */
+ if (!flag_objc_gc)
{
- if (PROPERTY_NAME (x) == DECL_NAME (decl))
+ if (!parsed_property_assign && !parsed_property_retain && !parsed_property_copy)
{
- error_at (location, "duplicate property declaration %qD", decl);
- return;
+ if (objc_type_valid_for_messaging (TREE_TYPE (decl)))
+ {
+ warning_at (location,
+ 0,
+ "object property %qD has no %<assign%>, %<retain%> or %<copy%> attribute; assuming %<assign%>",
+ decl);
+ inform (location,
+ "%<assign%> can be unsafe for Objective-C objects; please state explicitly if you need it");
+ }
}
}
- TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context);
- CLASS_PROPERTY_DECL (objc_interface_context) = property_decl;
}
- else
- {
- /* This case will go away once @syhtensize is implemented. */
+
+ if (property_assign_semantics == OBJC_PROPERTY_RETAIN
+ && !objc_type_valid_for_messaging (TREE_TYPE (decl)))
+ error_at (location, "%<retain%> attribute is only valid for Objective-C objects");
+
+ if (property_assign_semantics == OBJC_PROPERTY_COPY
+ && !objc_type_valid_for_messaging (TREE_TYPE (decl)))
+ error_at (location, "%<copy%> attribute is only valid for Objective-C objects");
- /* Doing the property in implementation context. */
- /* If property is not declared in the interface issue error. */
- for (x = CLASS_PROPERTY_DECL (interface); x; x = TREE_CHAIN (x))
- if (PROPERTY_NAME (x) == DECL_NAME (decl))
- break;
- if (!x)
+ /* Check for duplicate property declarations. We first check the
+ immediate context for a property with the same name. */
+ for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
+ {
+ if (PROPERTY_NAME (x) == DECL_NAME (decl))
{
- error_at (location, "no declaration of property %qD found in the interface", decl);
+ location_t original_location = DECL_SOURCE_LOCATION (x);
+
+ error_at (location, "redeclaration of property %qD", decl);
+
+ if (original_location != UNKNOWN_LOCATION)
+ inform (original_location, "originally declared here");
return;
- }
- /* readonlys must also match. */
- if (PROPERTY_READONLY (x) != PROPERTY_READONLY (property_decl))
- {
- error_at (location, "property %qD %<readonly%> attribute conflicts with its"
- " interface version", decl);
- }
- /* copies must also match. */
- if (PROPERTY_COPIES (x) != PROPERTY_COPIES (property_decl))
- {
- error_at (location, "property %qD %<copies%> attribute conflicts with its"
- " interface version", decl);
- }
- /* Cannot have readonly and setter attribute for the same property. */
- if (PROPERTY_READONLY (property_decl) == boolean_true_node &&
- PROPERTY_SETTER_NAME (property_decl))
- {
- /* This error is already reported up there. */
- /* warning_at (location, 0, "a %<readonly%> property cannot have a setter (ignored)"); */
- PROPERTY_SETTER_NAME (property_decl) = NULL_TREE;
- }
- /* Add the property to the list of properties for current implementation. */
- TREE_CHAIN (property_decl) = IMPL_PROPERTY_DECL (objc_implementation_context);
- IMPL_PROPERTY_DECL (objc_implementation_context) = property_decl;
+ }
}
+
+ /* TODO: Shall we check here for other property declaractions (in
+ the superclass, other categories or protocols) with the same name
+ and conflicting types ? */
+
+ /* Create a PROPERTY_DECL node. */
+ property_decl = make_node (PROPERTY_DECL);
+
+ /* Copy the basic information from the original decl. */
+ TREE_TYPE (property_decl) = TREE_TYPE (decl);
+ DECL_SOURCE_LOCATION (property_decl) = DECL_SOURCE_LOCATION (decl);
+ TREE_DEPRECATED (property_decl) = TREE_DEPRECATED (decl);
+
+ /* Add property-specific information. */
+ PROPERTY_NAME (property_decl) = DECL_NAME (decl);
+ PROPERTY_GETTER_NAME (property_decl) = parsed_property_getter_ident;
+ PROPERTY_SETTER_NAME (property_decl) = parsed_property_setter_ident;
+ PROPERTY_READONLY (property_decl) = property_readonly;
+ PROPERTY_NONATOMIC (property_decl) = parsed_property_nonatomic;
+ PROPERTY_ASSIGN_SEMANTICS (property_decl) = property_assign_semantics;
+ PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
+ PROPERTY_DYNAMIC (property_decl) = 0;
+
+ /* Add the PROPERTY_DECL to the list of properties for the class. */
+ TREE_CHAIN (property_decl) = CLASS_PROPERTY_DECL (objc_interface_context);
+ CLASS_PROPERTY_DECL (objc_interface_context) = property_decl;
}
/* This routine looks for a given PROPERTY in a list of CLASS, CATEGORY, or
- PROTOCOL.
-*/
+ PROTOCOL. */
static tree
lookup_property_in_list (tree chain, tree property)
{
@@ -1046,7 +1002,6 @@ lookup_property_in_list (tree chain, tree property)
}
/* This routine looks for a given PROPERTY in the tree chain of RPROTO_LIST. */
-
static tree lookup_property_in_protocol_list (tree rproto_list, tree property)
{
tree rproto, x;
@@ -1069,8 +1024,7 @@ static tree lookup_property_in_protocol_list (tree rproto_list, tree property)
}
/* This routine looks up the PROPERTY in current INTERFACE, its categories and up the
- chain of interface hierarchy.
-*/
+ chain of interface hierarchy. */
static tree
lookup_property (tree interface_type, tree property)
{
@@ -1098,33 +1052,42 @@ lookup_property (tree interface_type, tree property)
return inter;
}
-/* This routine recognizes a dot-notation for a property reference and generates a call to
- the getter function for this property. In all other cases, it returns a NULL_TREE.
-*/
+/* This hook routine is invoked by the parser when an expression such
+ as 'xxx.yyy' is parsed. We get a chance to process these
+ expressions in a way that is specified to Objective-C (to implement
+ properties, or non-fragile ivars). If the expression is not an
+ Objective-C specified expression, we should return NULL_TREE; else
+ we return the expression.
+
+ At the moment this only implements properties (not non-fragile
+ ivars yet), ie 'object.property'. */
tree
-objc_build_getter_call (tree receiver, tree component)
+objc_maybe_build_component_ref (tree object, tree property_ident)
{
tree x = NULL_TREE;
tree rtype;
- if (receiver == NULL_TREE
- || receiver == error_mark_node
- || (rtype = TREE_TYPE (receiver)) == NULL_TREE)
+ /* Try to determine quickly if 'object' is an Objective-C object or
+ not. If not, return. */
+ if (object == NULL_TREE || object == error_mark_node
+ || (rtype = TREE_TYPE (object)) == NULL_TREE)
return NULL_TREE;
-
- if (component == NULL_TREE
- || component == error_mark_node
- || TREE_CODE (component) != IDENTIFIER_NODE)
+
+ if (property_ident == NULL_TREE || property_ident == error_mark_node
+ || TREE_CODE (property_ident) != IDENTIFIER_NODE)
return NULL_TREE;
+ /* TODO: Implement super.property. */
+
+ /* TODO: Carefully review the following code. */
if (objc_is_id (rtype))
{
tree rprotos = (TYPE_HAS_OBJC_INFO (TREE_TYPE (rtype))
? TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (rtype))
: NULL_TREE);
if (rprotos)
- x = lookup_property_in_protocol_list (rprotos, component);
+ x = lookup_property_in_protocol_list (rprotos, property_ident);
}
else
{
@@ -1145,176 +1108,100 @@ objc_build_getter_call (tree receiver, tree component)
if (basetype != NULL_TREE && TYPED_OBJECT (basetype))
{
tree interface_type = TYPE_OBJC_INTERFACE (basetype);
- if (!interface_type)
- return NULL_TREE;
- x = lookup_property (interface_type, component);
+ tree protocol_list = TYPE_OBJC_PROTOCOL_LIST (basetype);
+
+ x = lookup_property (interface_type, property_ident);
+
+ if (x == NULL_TREE)
+ x = lookup_property_in_protocol_list (protocol_list, property_ident);
}
}
if (x)
{
- tree call_exp, getter;
- /* Get the getter name. */
- gcc_assert (PROPERTY_NAME (x));
- getter = objc_finish_message_expr (receiver, PROPERTY_NAME (x),
- NULL_TREE);
- call_exp = getter;
-#ifdef OBJCPLUS
- /* In C++, a getter which returns an aggregate value results in a
- target_expr which initializes a temporary to the call expression. */
- if (TREE_CODE (getter) == TARGET_EXPR)
- {
- gcc_assert (MAYBE_CLASS_TYPE_P (TREE_TYPE (getter)));
- gcc_assert (TREE_CODE (TREE_OPERAND (getter,0)) == VAR_DECL);
- call_exp = TREE_OPERAND (getter,1);
- }
-#endif
- gcc_assert (TREE_CODE (call_exp) == CALL_EXPR);
-
- CALL_EXPR_OBJC_PROPERTY_GETTER (call_exp) = 1;
- return getter;
+ tree expression;
+
+ expression = build2 (PROPERTY_REF, TREE_TYPE(x), object, x);
+ SET_EXPR_LOCATION (expression, input_location);
+ TREE_SIDE_EFFECTS (expression) = 1;
+
+ /* We have an additional nasty problem here; if this
+ PROPERTY_REF needs to become a 'getter', then the conversion
+ from PROPERTY_REF into a getter call happens in gimplify,
+ after the selector table has already been generated and it is
+ too late to add another selector to it. To work around the
+ problem, we always put the selector in the table at this
+ stage, as if we were building the method call here. And the
+ easiest way to do this is precisely to build the method call,
+ then discard it. Note that if the PROPERTY_REF becomes a
+ 'setter' instead of a 'getter', then we have added a selector
+ too many to the selector table. This is a little
+ inefficient.
+
+ TODO: This can be made more efficient; in particular we don't
+ need to build the whole message call, we could just work on
+ the selector. */
+ objc_finish_message_expr (object,
+ PROPERTY_GETTER_NAME (x),
+ NULL_TREE);
+
+ return expression;
}
- return NULL_TREE;
-}
-
-/* This routine builds a call to property's 'setter' function. RECEIVER is the
- receiving object for 'setter'. PROPERTY_IDENT is name of the property and
- RHS is the argument passed to the 'setter' function. */
-static tree
-objc_setter_func_call (tree receiver, tree property_ident, tree rhs)
-{
- tree setter_argument = build_tree_list (NULL_TREE, rhs);
- char *setter_name = objc_build_property_setter_name (property_ident, true);
- tree setter;
- in_objc_property_setter_name_context = true;
- setter = objc_finish_message_expr (receiver, get_identifier (setter_name),
- setter_argument);
- in_objc_property_setter_name_context = false;
- return setter;
+ return NULL_TREE;
}
-/* Find the selector identifier from a reference. A somewhat tortuous way of
- obtaining the information to allow a setter to be written, given an
- existing getter. */
-
-static tree
-get_selector_from_reference (tree selref)
+/* This is used because we don't want to expose PROPERTY_REF to the
+ C/C++ frontends. Maybe we should! */
+bool
+objc_is_property_ref (tree node)
{
- tree chain;
-
- if (flag_next_runtime)
- {
- /* Run through the selectors until we find the one we're looking for. */
- for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
- if (TREE_PURPOSE (chain) == selref)
- return TREE_VALUE (chain);
- }
+ if (node && TREE_CODE (node) == PROPERTY_REF)
+ return true;
else
- {
- /* To find our way back to the selector for the GNU runtime is harder
- work, we need to decompose the representation of SELECTOR_TABLE[n]
- to find 'n'. This representation is in several forms. */
- if (TREE_CODE (selref) == POINTER_PLUS_EXPR)
- {
- /* We need the element size to decode the array offset expression
- into an index. */
- unsigned size = (unsigned) TREE_INT_CST_LOW
- (TYPE_SIZE_UNIT
- (TREE_TYPE
- (TREE_TYPE
- (TREE_OPERAND
- (TREE_OPERAND
- (TREE_OPERAND (selref, 0), 0), 0)))));
- unsigned index =
- (unsigned) TREE_INT_CST_LOW (TREE_OPERAND (selref, 1))
- / size;
- for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
- if (!index--)
- return TREE_VALUE (chain);
- }
- else if (TREE_CODE (selref) == NOP_EXPR)
- {
- /* Either we have a base an index, or we have just a base (when the
- index is 0. */
- if (TREE_CODE (TREE_OPERAND (selref, 0)) == ADDR_EXPR
- && TREE_CODE
- (TREE_OPERAND
- (TREE_OPERAND (selref, 0), 0)) == ARRAY_REF)
- {
- /* The Nth. */
- unsigned index = (unsigned) TREE_INT_CST_LOW
- (TREE_OPERAND
- (TREE_OPERAND
- (TREE_OPERAND (selref, 0), 0), 1));
- for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
- if (!index--)
- return TREE_VALUE (chain);
- }
- else
- return TREE_VALUE (sel_ref_chain);
- } /* Else we don't know how to figure this out - which will produce a
- parse error - saying that the LHS is not writeable. */
- }
- return NULL_TREE;
-}
-
-/* This routine converts a previously synthesized 'getter' function call for
- a property and converts it to a 'setter' function call for the same
- property. */
-
-tree
-objc_build_setter_call (tree lhs, tree rhs)
-{
- if (lhs
- && TREE_CODE (lhs) == CALL_EXPR
- && CALL_EXPR_OBJC_PROPERTY_GETTER (lhs))
- {
- tree selector;
- /* Get the Object. */
- tree receiver = TREE_OPERAND (lhs, 3);
- /* Get the selector reference. */
- tree selector_reference = TREE_OPERAND (lhs, 4);
- gcc_assert (receiver && selector_reference);
- /* The style of the selector reference is different for GNU & NeXT. */
- selector = get_selector_from_reference (selector_reference);
- if (selector)
- return objc_setter_func_call (receiver, selector, rhs);
- }
- return NULL_TREE;
+ return false;
}
-/* This routine checks to see if ID is a property name. If so, it
- returns property declaration. */
+/* This hook routine is called when a MODIFY_EXPR is being built. We
+ check what is being modified; if it is a PROPERTY_REF, we need to
+ generate a 'setter' function call for the property. If this is not
+ a PROPERTY_REF, we return NULL_TREE and the C/C++ frontend will go
+ on creating their MODIFY_EXPR.
-static tree
-is_property (tree klass, tree id)
-{
- tree x;
+ This is used for example if you write
- for (x = CLASS_PROPERTY_DECL (klass); x; x = TREE_CHAIN (x))
- if (PROPERTY_NAME (x) == id)
- return x;
- return NULL_TREE;
-}
-
-/* This routine returns call to property's getter when a property is
- used stand-alone (without self. notation). */
+ object.count = 1;
-static tree
-build_property_reference (tree property, tree id)
+ where 'count' is a property. The left-hand side creates a
+ PROPERTY_REF, and then the compiler tries to generate a MODIFY_EXPR
+ to assign something to it. We intercept that here, and generate a
+ call to the 'setter' method instead. */
+tree
+objc_maybe_build_modify_expr (tree lhs, tree rhs)
{
- tree getter;
- if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
+ if (lhs && TREE_CODE (lhs) == PROPERTY_REF)
{
- error ("property %qs accessed in class method",
- IDENTIFIER_POINTER (id));
- return error_mark_node;
- }
+ tree object_expr = PROPERTY_REF_OBJECT (lhs);
+ tree property_decl = PROPERTY_REF_PROPERTY_DECL (lhs);
- getter = objc_finish_message_expr (self_decl, PROPERTY_NAME (property), NULL_TREE);
- CALL_EXPR_OBJC_PROPERTY_GETTER (getter) = 1;
- return getter;
+ if (PROPERTY_READONLY (property_decl))
+ {
+ error ("readonly property can not be set");
+ return error_mark_node;
+ }
+ else
+ {
+ tree setter_argument = build_tree_list (NULL_TREE, rhs);
+ tree setter;
+ /* TODO: Decay argument in C. */
+ setter = objc_finish_message_expr (object_expr,
+ PROPERTY_SETTER_NAME (property_decl),
+ setter_argument);
+ return setter;
+ }
+ }
+ else
+ return NULL_TREE;
}
tree
@@ -7226,9 +7113,7 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params)
= lookup_method_in_hash_lists (sel_name, class_tree != NULL_TREE);
}
- if (!method_prototype && in_objc_property_setter_name_context)
- error ("readonly property can not be set");
- else if (!method_prototype)
+ if (!method_prototype)
{
static bool warn_missing_methods = false;
@@ -8164,6 +8049,16 @@ check_methods (tree chain, tree list, int mtype)
while (chain)
{
+ /* If the method is associated with a dynamic property, then it
+ is Ok not to have the method implementation, as it will be
+ generated dynamically at runtime. */
+ tree property = METHOD_PROPERTY_CONTEXT (chain);
+ if (property != NULL_TREE && PROPERTY_DYNAMIC (property))
+ {
+ chain = TREE_CHAIN (chain); /* next method... */
+ continue;
+ }
+
if (!lookup_method (list, chain))
{
if (first)
@@ -8231,6 +8126,16 @@ check_methods_accessible (tree chain, tree context, int mtype)
while (chain)
{
+ /* If the method is associated with a dynamic property, then it
+ is Ok not to have the method implementation, as it will be
+ generated dynamically at runtime. */
+ tree property = METHOD_PROPERTY_CONTEXT (chain);
+ if (property != NULL_TREE && PROPERTY_DYNAMIC (property))
+ {
+ chain = TREE_CHAIN (chain); /* next method... */
+ continue;
+ }
+
context = base_context;
while (context)
{
@@ -8600,199 +8505,67 @@ continue_class (tree klass)
}
}
-/* This routine builds a property ivar name. */
-
-static char *
-objc_build_property_ivar_name (tree property_decl)
-{
- static char string[BUFSIZE];
- sprintf (string, "_%s", IDENTIFIER_POINTER (PROPERTY_NAME (property_decl)));
- return string;
-}
-
/* This routine builds name of the setter synthesized function. */
-
static char *
-objc_build_property_setter_name (tree ident, bool delimit_colon)
+objc_build_property_setter_name (tree ident)
{
+ /* TODO: Use alloca to allocate buffer of appropriate size. */
static char string[BUFSIZE];
- if (delimit_colon)
- sprintf (string, "set%s:", IDENTIFIER_POINTER (ident));
- else
- sprintf (string, "set%s", IDENTIFIER_POINTER (ident));
+ sprintf (string, "set%s:", IDENTIFIER_POINTER (ident));
string[3] = TOUPPER (string[3]);
return string;
}
-/* This routine does all the work for generating data and code per each
- property declared in current implementation. */
-
+/* This routine synthesizes a 'getter' method. This is only called
+ for @synthesize properties. */
static void
-objc_gen_one_property_datum (tree klass, tree property, tree class_methods, bool *ivar_added)
-{
- tree mth;
-
- /* If getter, check that it is already declared in user code. */
- if (PROPERTY_GETTER_NAME (property))
- {
- mth = lookup_method (CLASS_NST_METHODS (class_methods),
- PROPERTY_GETTER_NAME (property));
- if (!mth)
- error ("property getter %qs not declared in class %qs",
- IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property)),
- IDENTIFIER_POINTER (CLASS_NAME (class_methods)));
- }
- /* If setter, check that it is already declared in user code. */
- if (PROPERTY_SETTER_NAME (property))
- {
- mth = lookup_method (CLASS_NST_METHODS (class_methods),
- PROPERTY_SETTER_NAME (property));
- if (!mth)
- error ("property setter %qs not declared in class %qs",
- IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property)),
- IDENTIFIER_POINTER (CLASS_NAME (class_methods)));
- }
- /* If ivar attribute specified, check that it is already declared. */
- if (PROPERTY_IVAR_NAME (property))
- {
- if (!is_ivar (CLASS_IVARS (klass),
- PROPERTY_IVAR_NAME (property)))
- error ("ivar %qs in property declaration must be an existing ivar",
- IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property)));
- }
- else if (!PROPERTY_GETTER_NAME (property)
- || (PROPERTY_READONLY (property) == boolean_false_node
- && !PROPERTY_SETTER_NAME (property)))
- {
- /* Setter and/or getter must be synthesize and there was no user-specified
- ivar. Must create an ivar and add to to current class's ivar list. */
- tree record = CLASS_STATIC_TEMPLATE (klass);
- tree type = TREE_TYPE (property);
- tree field_decl, field;
- field_decl = create_field_decl (type,
- objc_build_property_ivar_name (property));
- DECL_CONTEXT (field_decl) = record;
- (void) add_instance_variable (klass,
- OBJC_IVAR_VIS_PUBLIC, field_decl);
- /* Unfortunately, CLASS_IVARS is completed when interface is completed.
- Must add the new ivar by hand to its list here. */
-
- CLASS_IVARS (klass) =
- chainon (CLASS_IVARS (klass),
- copy_node (field_decl));
- gcc_assert (record);
- /* Must also add this ivar to the end of list of fields for this class. */
- field = TYPE_FIELDS (record);
- if (field && field != CLASS_IVARS (klass))
- /* class has a hidden field, attach ivar list after the hiddent field. */
- TREE_CHAIN (field) = CLASS_IVARS (klass);
- else
- TYPE_FIELDS (record) = CLASS_IVARS (klass);
- *ivar_added = true;
- }
-}
-
-/* This routine processes an existing getter or setter attribute.
- It aliases internal property getter or setter to the user implemented
- getter or setter.
-*/
-
-static void
-objc_process_getter_setter (tree klass, tree property, bool getter)
-{
- tree prop_mth_decl;
- tree prop_getter_mth_decl;
- tree name_ident;
-
- if (getter)
- /* getter name is same as property name. */
- name_ident = PROPERTY_NAME (property);
- else
- /* Must synthesize setter name from property name. */
- name_ident = get_identifier (objc_build_property_setter_name (
- PROPERTY_NAME (property), true));
-
- /* Find declaration of instance method for the property in its class. */
- prop_mth_decl = lookup_method (CLASS_NST_METHODS (klass), name_ident);
-
- if (!prop_mth_decl)
- return;
-
- prop_getter_mth_decl = lookup_method (CLASS_NST_METHODS (objc_implementation_context),
- getter ? PROPERTY_GETTER_NAME (property)
- : PROPERTY_SETTER_NAME (property));
-
- if (!prop_getter_mth_decl)
- return;
-
- if (!match_proto_with_proto (prop_getter_mth_decl, prop_mth_decl, 1))
- {
- error ("User %s %qs does not match property %qs type",
- getter ? "getter" : "setter",
- IDENTIFIER_POINTER (DECL_NAME (prop_getter_mth_decl)),
- IDENTIFIER_POINTER (PROPERTY_NAME (property)));
- return;
- }
- /* We alias internal property getter to the user implemented getter by copying relevant
- entries from user's implementation to the internal one. */
- prop_mth_decl = copy_node (prop_mth_decl);
- METHOD_ENCODING (prop_mth_decl) = METHOD_ENCODING (prop_getter_mth_decl);
- METHOD_DEFINITION (prop_mth_decl) = METHOD_DEFINITION (prop_getter_mth_decl);
- objc_add_method (objc_implementation_context, prop_mth_decl, 0, 0);
-}
-
-/* This routine synthesizes a 'getter' method. */
-
-static void
-objc_synthesize_getter (tree klass, tree class_method, tree property)
+objc_synthesize_getter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property)
{
tree fn, decl;
tree body;
tree ret_val;
- tree ivar_ident;
- /* If user has implemented a getter with same name then do nothing. */
+ /* If user has implemented a getter with same name then do nothing. */
if (lookup_method (CLASS_NST_METHODS (objc_implementation_context),
- PROPERTY_NAME (property)))
+ PROPERTY_GETTER_NAME (property)))
return;
- /* Find declaration of the property in the interface. There must be one. */
- decl = lookup_method (CLASS_NST_METHODS (class_method),
- PROPERTY_NAME (property));
+ /* Find declaration of the property getter in the interface. There
+ must be one. TODO: Search superclasses as well. */
+ decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_GETTER_NAME (property));
- /* If one not declared in the interface, this condition has already been reported
- as user error (because property was not declared in the interface). */
+ /* If one not declared in the interface, this condition has already
+ been reported as user error (because property was not declared in
+ the interface). */
if (!decl)
return;
- /* For now no attributes. */
- objc_start_method_definition (false /* is_class_method */, copy_node (decl), NULL_TREE);
+ /* Adapt the 'decl'. Use the source location of the @synthesize
+ statement for error messages. */
+ decl = copy_node (decl);
+ DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (property);
+ objc_start_method_definition (false /* is_class_method */, decl, NULL_TREE);
body = c_begin_compound_stmt (true);
+
+ /* TODO: Implement PROPERTY_NONATOMIC, use objc_getProperty etc as
+ appropriate. The following code just always does direct ivar
+ access. */
+
/* return self->_property_name; */
- /* If user specified an ivar, use it in generation of the getter. */
- ivar_ident = PROPERTY_IVAR_NAME (property)
- ? PROPERTY_IVAR_NAME (property)
- : get_identifier (objc_build_property_ivar_name (property));
-
- /* objc_ivar_chain might not be up to date in the case that property 'ivar'
- is added *after* user ivar is parsed and objc_continue_implementation
- has already been called. */
- objc_ivar_chain = CLASS_IVARS (klass);
- ret_val = objc_lookup_ivar (NULL_TREE, ivar_ident);
- /* If ivar attribute is not a user declared attribute, this condition has
- already been repored as error. */
- gcc_assert (ret_val || PROPERTY_IVAR_NAME (property));
-
- if (ret_val)
- {
+
+ /* PROPERTY_IVAR_NAME is always defined if we got here, and should
+ be a valid instance variable. */
+ ret_val = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property));
+ gcc_assert (ret_val);
+
#ifdef OBJCPLUS
- finish_return_stmt (ret_val);
+ finish_return_stmt (ret_val);
#else
- (void)c_finish_return (input_location, ret_val, NULL);
+ (void)c_finish_return (DECL_SOURCE_LOCATION (property), ret_val, NULL);
#endif
- }
- add_stmt (c_end_compound_stmt (input_location, body, true));
+
+ add_stmt (c_end_compound_stmt (DECL_SOURCE_LOCATION (property), body, true));
fn = current_function_decl;
#ifdef OBJCPLUS
finish_function ();
@@ -8803,55 +8576,69 @@ objc_synthesize_getter (tree klass, tree class_method, tree property)
/* This routine synthesizes a 'setter' method. */
static void
-objc_synthesize_setter (tree klass, tree class_method, tree property)
+objc_synthesize_setter (tree klass ATTRIBUTE_UNUSED, tree class_method, tree property)
{
- tree fn, decl, ivar_ident, lhs, rhs;
+ tree fn, decl, lhs, rhs;
tree body;
- char *setter_name = objc_build_property_setter_name (
- PROPERTY_NAME (property), true);
- tree setter_ident = get_identifier (setter_name);
- /* If user has implemented a setter with same name then do nothing. */
+ /* If user has implemented a setter with same name then do nothing. */
if (lookup_method (CLASS_NST_METHODS (objc_implementation_context),
- setter_ident))
+ PROPERTY_SETTER_NAME (property)))
return;
- /* Find declaration of the property in the interface. There must be one. */
- decl = lookup_method (CLASS_NST_METHODS (class_method), setter_ident);
+ /* Find declaration of the property setter in the interface. There
+ must be one. TODO: Search superclasses as well. */
+ decl = lookup_method (CLASS_NST_METHODS (class_method), PROPERTY_SETTER_NAME (property));
- /* If one not declared in the inerface, this condition has already been reported
- as user error (because property was not declared in the interface. */
+ /* If one not declared in the interface, this condition has already
+ been reported as user error (because property was not declared in
+ the interface). */
if (!decl)
return;
- /* For now, no attributes. */
- objc_start_method_definition (false /* is_class_method */, copy_node (decl), NULL_TREE);
+ /* Adapt the 'decl'. Use the source location of the @synthesize
+ statement for error messages. */
+ decl = copy_node (decl);
+ DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (property);
+
+ objc_start_method_definition (false /* is_class_method */, decl, NULL_TREE);
body = c_begin_compound_stmt (true);
+
+ /* TODO: Implement PROPERTY_NONATOMIC, use objc_getProperty etc as
+ appropriate. The following code just always does direct ivar
+ access. */
+
/* _property_name = _value; */
- /* If user specified an ivar, use it in generation of the setter. */
- ivar_ident = PROPERTY_IVAR_NAME (property)
- ? PROPERTY_IVAR_NAME (property)
- : get_identifier (objc_build_property_ivar_name (property));
-
- /* objc_ivar_chain might not be up to date in the case that property 'ivar'
- is added *after* user ivar is parsed and objc_continue_implementation
- has already been called. */
- objc_ivar_chain = CLASS_IVARS (klass);
- lhs = objc_lookup_ivar (NULL_TREE, ivar_ident);
- /* If ivar attribute is not a user declared attribute, this condition has
- already been repored as error. */
- gcc_assert (lhs || PROPERTY_IVAR_NAME (property));
- if (lhs)
- {
- rhs = lookup_name (get_identifier ("_value"));
- gcc_assert (rhs);
- /* FIXME: NULL types to get compile. */
- add_stmt (build_modify_expr (input_location,
- lhs, NULL_TREE, NOP_EXPR,
- input_location, rhs, NULL_TREE));
- }
- add_stmt (c_end_compound_stmt (input_location, body, true));
+
+ /* PROPERTY_IVAR_NAME is always defined if we got here, and should
+ be a valid instance variable. */
+ lhs = objc_lookup_ivar (NULL_TREE, PROPERTY_IVAR_NAME (property));
+ gcc_assert (lhs);
+
+ /* TODO: Lookup the argument in a more robust way so that it works
+ even if the method prototype does not call it '_value'. */
+ rhs = lookup_name (get_identifier ("_value"));
+
+ /* This would presumably happen if the user has specified a
+ prototype for the setter that is not the correct one. */
+ if (rhs == NULL_TREE)
+ {
+ /* TODO: This should be caught much earlier than this. */
+ /* We couldn't find the '_value' identifier in the current
+ context; presumably the user didn't have a '_value'
+ argument. */
+ error_at (DECL_SOURCE_LOCATION (decl), "invalid setter, missing _value argument");
+ /* Just recover somehow. */
+ rhs = lhs;
+ }
+
+ /* FIXME: NULL types to get compile. */
+ add_stmt (build_modify_expr (DECL_SOURCE_LOCATION (decl),
+ lhs, NULL_TREE, NOP_EXPR,
+ DECL_SOURCE_LOCATION (decl), rhs, NULL_TREE));
+
+ add_stmt (c_end_compound_stmt (DECL_SOURCE_LOCATION (decl), body, true));
fn = current_function_decl;
#ifdef OBJCPLUS
finish_function ();
@@ -8859,14 +8646,104 @@ objc_synthesize_setter (tree klass, tree class_method, tree property)
objc_finish_method_definition (fn);
}
+/* This function is a sub-routine of objc_add_synthesize_declaration.
+ It is called for each property to synthesize once we have
+ determined that the context is Ok. */
+static void
+objc_add_synthesize_declaration_for_property (location_t location, tree interface,
+ tree property_name, tree ivar_name)
+{
+ /* Find the @property declaration. */
+ tree property;
+
+ /* Check that synthesize or dynamic has not already been used for
+ the same property. */
+ for (property = CLASS_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
+ if (PROPERTY_NAME (property) == property_name)
+ {
+ location_t original_location = DECL_SOURCE_LOCATION (property);
+
+ if (PROPERTY_DYNAMIC (property))
+ error_at (location, "property %qs already specified in %<@dynamic%>",
+ IDENTIFIER_POINTER (property_name));
+ else
+ error_at (location, "property %qs already specified in %<@synthesize%>",
+ IDENTIFIER_POINTER (property_name));
+
+ if (original_location != UNKNOWN_LOCATION)
+ inform (original_location, "originally specified here");
+ return;
+ }
+
+ /* Check that the property is declared in the interface. */
+ /* TODO: This only check the immediate class; we need to check the
+ superclass (and categories ?) as well. */
+ for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property))
+ if (PROPERTY_NAME (property) == property_name)
+ break;
+
+ if (!property)
+ {
+ error_at (location, "no declaration of property %qs found in the interface",
+ IDENTIFIER_POINTER (property_name));
+ return;
+ }
+ else
+ {
+ /* We have to copy the property, because we want to chain it to
+ the implementation context, and we want to store the source
+ location of the @synthesize, not of the original
+ @property. */
+ property = copy_node (property);
+ DECL_SOURCE_LOCATION (property) = location;
+ }
+
+ /* Determine PROPERTY_IVAR_NAME. */
+ if (ivar_name == NULL_TREE)
+ ivar_name = property_name;
+
+ /* Check that the instance variable exists. You can only use an
+ instance variable from the same class, not one from the
+ superclass. */
+ if (!is_ivar (CLASS_IVARS (interface), ivar_name))
+ error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar",
+ IDENTIFIER_POINTER (property_name));
+
+ /* TODO: Check that the types of the instance variable and of the
+ property match. */
+
+ /* TODO: Check that no other property is using the same instance
+ variable. */
+
+ /* Note that a @synthesize (and only a @synthesize) always sets
+ PROPERTY_IVAR_NAME to a non-NULL_TREE. You can recognize a
+ @synthesize by that. */
+ PROPERTY_IVAR_NAME (property) = ivar_name;
+
+ /* PROPERTY_SETTER_NAME and PROPERTY_GETTER_NAME are copied from the
+ original declaration; they are always set (with the exception of
+ PROPERTY_SETTER_NAME not being set if PROPERTY_READONLY == 1). */
+
+ /* Add the property to the list of properties for current implementation. */
+ TREE_CHAIN (property) = IMPL_PROPERTY_DECL (objc_implementation_context);
+ IMPL_PROPERTY_DECL (objc_implementation_context) = property;
+
+ /* Note how we don't actually synthesize the getter/setter here; it
+ would be very natural, but we may miss the fact that the user has
+ implemented his own getter/setter later on in the @implementation
+ (in which case we shouldn't generate getter/setter). We wait
+ until we have parsed it all before generating the code. */
+}
+
/* This function is called by the parser after a @synthesize
- expression is parsed. 'start_locus' is the location of the
+ expression is parsed. 'location' is the location of the
@synthesize expression, and 'property_and_ivar_list' is a chained
- list of the property and ivar names.
- */
+ list of the property and ivar names. */
void
-objc_add_synthesize_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree property_and_ivar_list ATTRIBUTE_UNUSED)
+objc_add_synthesize_declaration (location_t location, tree property_and_ivar_list)
{
+ tree interface, chain;
+
if (property_and_ivar_list == error_mark_node)
return;
@@ -8876,21 +8753,117 @@ objc_add_synthesize_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree p
detects the problem while parsing, outputs the error
"misplaced '@synthesize' Objective-C++ construct" and skips
the declaration. */
- error ("%<@synthesize%> not in @implementation context");
+ error_at (location, "%<@synthesize%> not in @implementation context");
+ return;
+ }
+
+ if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
+ {
+ /* TODO: Maybe we should allow @synthesize in categories ? */
+ error_at (location, "%<@synthesize%> can not be used in categories");
+ return;
+ }
+
+ interface = lookup_interface (CLASS_NAME (objc_implementation_context));
+ if (!interface)
+ {
+ /* I can't see how this could happen, but it is good as a safety check. */
+ error_at (location,
+ "%<@synthesize%> requires the @interface of the class to be available");
+ return;
+ }
+
+ /* Now, iterate over the properties and do each of them. */
+ for (chain = property_and_ivar_list; chain; chain = TREE_CHAIN (chain))
+ {
+ objc_add_synthesize_declaration_for_property (location, interface, TREE_VALUE (chain),
+ TREE_PURPOSE (chain));
+ }
+}
+
+/* This function is a sub-routine of objc_add_dynamic_declaration. It
+ is called for each property to mark as dynamic once we have
+ determined that the context is Ok. */
+static void
+objc_add_dynamic_declaration_for_property (location_t location, tree interface,
+ tree property_name)
+{
+ /* Find the @property declaration. */
+ tree property;
+
+ /* Check that synthesize or dynamic has not already been used for
+ the same property. */
+ for (property = CLASS_PROPERTY_DECL (objc_implementation_context); property; property = TREE_CHAIN (property))
+ if (PROPERTY_NAME (property) == property_name)
+ {
+ location_t original_location = DECL_SOURCE_LOCATION (property);
+
+ if (PROPERTY_DYNAMIC (property))
+ error_at (location, "property %qs already specified in %<@dynamic%>",
+ IDENTIFIER_POINTER (property_name));
+ else
+ error_at (location, "property %qs already specified in %<@synthesize%>",
+ IDENTIFIER_POINTER (property_name));
+
+ if (original_location != UNKNOWN_LOCATION)
+ inform (original_location, "originally specified here");
+ return;
+ }
+
+ /* Check that the property is declared in the interface. */
+ /* TODO: This only check the immediate class; we need to check the
+ superclass (and categories ?) as well. */
+ for (property = CLASS_PROPERTY_DECL (interface); property; property = TREE_CHAIN (property))
+ if (PROPERTY_NAME (property) == property_name)
+ break;
+
+ if (!property)
+ {
+ error_at (location, "no declaration of property %qs found in the interface",
+ IDENTIFIER_POINTER (property_name));
return;
}
+ else
+ {
+ /* Mark the original PROPERTY_DECL as dynamic. The reason is
+ that the setter and getter methods in the interface have a
+ METHOD_PROPERTY_CONTEXT that points to the original
+ PROPERTY_DECL; when we check that these methods have been
+ implemented, we need to easily find that they are associated
+ with a dynamic property. TODO: Clean this up; maybe the
+ @property PROPERTY_DECL should contain a reference to the
+ @dynamic PROPERTY_DECL ? */
+ PROPERTY_DYNAMIC (property) = 1;
+
+ /* We have to copy the property, because we want to chain it to
+ the implementation context, and we want to store the source
+ location of the @synthesize, not of the original
+ @property. */
+ property = copy_node (property);
+ DECL_SOURCE_LOCATION (property) = location;
+ }
+
+ /* Note that a @dynamic (and only a @dynamic) always sets
+ PROPERTY_DYNAMIC to 1. You can recognize a @dynamic by that.
+ (actually, as explained above, PROPERTY_DECL generated by
+ @property and associated with a @dynamic property are also marked
+ as PROPERTY_DYNAMIC). */
+ PROPERTY_DYNAMIC (property) = 1;
- /* TODO */
- error ("%<@synthesize%> is not supported in this version of the compiler");
+ /* Add the property to the list of properties for current implementation. */
+ TREE_CHAIN (property) = IMPL_PROPERTY_DECL (objc_implementation_context);
+ IMPL_PROPERTY_DECL (objc_implementation_context) = property;
}
/* This function is called by the parser after a @dynamic expression
- is parsed. 'start_locus' is the location of the @dynamic
- expression, and 'property_list' is a chained list of all the
- property names. */
+ is parsed. 'location' is the location of the @dynamic expression,
+ and 'property_list' is a chained list of all the property
+ names. */
void
-objc_add_dynamic_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree property_list ATTRIBUTE_UNUSED)
+objc_add_dynamic_declaration (location_t location, tree property_list)
{
+ tree interface, chain;
+
if (property_list == error_mark_node)
return;
@@ -8900,12 +8873,31 @@ objc_add_dynamic_declaration (location_t start_locus ATTRIBUTE_UNUSED, tree prop
detects the problem while parsing, outputs the error
"misplaced '@dynamic' Objective-C++ construct" and skips the
declaration. */
- error ("%<@dynamic%> not in @implementation context");
+ error_at (location, "%<@dynamic%> not in @implementation context");
return;
}
- /* TODO */
- error ("%<@dynamic%> is not supported in this version of the compiler");
+ if (TREE_CODE (objc_implementation_context) == CATEGORY_IMPLEMENTATION_TYPE)
+ {
+ /* TODO: Maybe we should allow @dynamic in categories ? */
+ error_at (location, "%<@dynamic%> can not be used in categories");
+ return;
+ }
+
+ interface = lookup_interface (CLASS_NAME (objc_implementation_context));
+ if (!interface)
+ {
+ /* I can't see how this could happen, but it is good as a safety check. */
+ error_at (location,
+ "%<@dynamic%> requires the @interface of the class to be available");
+ return;
+ }
+
+ /* Now, iterate over the properties and do each of them. */
+ for (chain = property_list; chain; chain = TREE_CHAIN (chain))
+ {
+ objc_add_dynamic_declaration_for_property (location, interface, TREE_VALUE (chain));
+ }
}
/* Main routine to generate code/data for all the property information for
@@ -8918,35 +8910,25 @@ static void
objc_gen_property_data (tree klass, tree class_methods)
{
tree x;
- bool ivar_added = false;
- for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x))
- objc_gen_one_property_datum (klass, x, class_methods, &ivar_added);
- if (ivar_added)
- {
- tree record = CLASS_STATIC_TEMPLATE (klass);
- /* Ugh, must recalculate struct layout since at least one ivar was added. */
- TYPE_SIZE (record) = 0;
- layout_type (record);
- }
-
- /* Synthesize all getters for properties. */
for (x = IMPL_PROPERTY_DECL (objc_implementation_context); x; x = TREE_CHAIN (x))
{
- /* Property has a getter attribute, no need to synthesize one. */
- if (PROPERTY_GETTER_NAME (x) == NULL_TREE)
- objc_synthesize_getter (klass, class_methods, x);
- else
- objc_process_getter_setter (class_methods, x, true);
-
- if (PROPERTY_READONLY (x) == boolean_false_node)
- {
- /* not a readonly property. */
- if (PROPERTY_SETTER_NAME (x) == NULL_TREE)
- objc_synthesize_setter (klass, class_methods, x);
- else
- objc_process_getter_setter (class_methods, x, false);
- }
+ /* @dynamic property - nothing to check or synthesize. */
+ if (PROPERTY_DYNAMIC (x))
+ continue;
+
+ /* @synthesize property - need to synthesize the accessors. */
+ if (PROPERTY_IVAR_NAME (x))
+ {
+ objc_synthesize_getter (klass, class_methods, x);
+
+ if (PROPERTY_READONLY (x) == 0)
+ objc_synthesize_setter (klass, class_methods, x);
+
+ continue;
+ }
+
+ gcc_unreachable ();
}
}
@@ -9001,60 +8983,119 @@ finish_class (tree klass)
}
break;
}
- default:
+ case CLASS_INTERFACE_TYPE:
+ case CATEGORY_INTERFACE_TYPE:
+ case PROTOCOL_INTERFACE_TYPE:
{
/* Process properties of the class. */
tree x;
for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
{
- tree type = TREE_TYPE (x);
- tree prop_name = PROPERTY_NAME (x);
- /* Build an instance method declaration: - (type) prop_name; */
+ /* Store the getter name that we used into the property.
+ It is used to generate the right getter calls;
+ moreover, when a @synthesize is processed, it copies
+ everything from the property, including the
+ PROPERTY_GETTER_NAME. We want to be sure that
+ @synthesize will get exactly the right
+ PROPERTY_GETTER_NAME. */
if (PROPERTY_GETTER_NAME (x) == NULL_TREE)
+ PROPERTY_GETTER_NAME (x) = PROPERTY_NAME (x);
+
+ /* Now we check that the appropriate getter is declared,
+ and if not, we declare one ourselves. */
+ {
+ tree getter_decl = lookup_method (CLASS_NST_METHODS (klass),
+ PROPERTY_GETTER_NAME (x));
+
+ if (getter_decl)
+ {
+ /* TODO: Check that the declaration is consistent with the property. */
+ ;
+ }
+ else
+ {
+ /* Generate an instance method declaration for the
+ getter; for example "- (id) name;". In general
+ it will be of the form
+ -(type)property_getter_name; */
+ tree rettype = build_tree_list (NULL_TREE, TREE_TYPE (x));
+ getter_decl = build_method_decl (INSTANCE_METHOD_DECL,
+ rettype, PROPERTY_GETTER_NAME (x),
+ NULL_TREE, false);
+ objc_add_method (objc_interface_context, getter_decl, false, false);
+ METHOD_PROPERTY_CONTEXT (getter_decl) = x;
+ }
+ }
+
+ if (PROPERTY_READONLY (x) == 0)
{
- /* No getter attribute specified. Generate an instance method for the
- getter. */
- tree rettype = build_tree_list (NULL_TREE, type);
- tree getter_decl = build_method_decl (INSTANCE_METHOD_DECL,
- rettype, prop_name,
- NULL_TREE, false);
- objc_add_method (objc_interface_context, getter_decl, false, false);
- METHOD_PROPERTY_CONTEXT (getter_decl) = x;
- }
- else
- warning (0, "getter = %qs may not be specified in an interface",
- IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (x)));
-
- /* Build an instance method declaration: - (void) setName: (type)value; */
- if (PROPERTY_SETTER_NAME (x) == NULL_TREE
- && PROPERTY_READONLY (x) == boolean_false_node)
- {
- /* Declare a setter instance method in the interface. */
- tree key_name, arg_type, arg_name;
- tree setter_decl, selector;
- tree ret_type = build_tree_list (NULL_TREE, void_type_node);
- /* setter name. */
- key_name = get_identifier (objc_build_property_setter_name
- (PROPERTY_NAME (x), false));
- arg_type = build_tree_list (NULL_TREE, type);
- arg_name = get_identifier ("_value");
- /* For now, no attributes. */
- selector = objc_build_keyword_decl (key_name, arg_type, arg_name, NULL);
- setter_decl = build_method_decl (INSTANCE_METHOD_DECL,
- ret_type, selector,
- build_tree_list (NULL_TREE, NULL_TREE),
- false);
- objc_add_method (objc_interface_context, setter_decl, false, false);
- METHOD_PROPERTY_CONTEXT (setter_decl) = x;
+ /* Store the setter name that we used into the
+ property. It is used when generating setter calls;
+ moreover, when a @synthesize is processed, it
+ copies everything from the property, including the
+ PROPERTY_SETTER_NAME. We want to be sure that
+ @synthesize will get exactly the right
+ PROPERTY_SETTER_NAME. */
+ if (PROPERTY_SETTER_NAME (x) == NULL_TREE)
+ PROPERTY_SETTER_NAME (x) = get_identifier (objc_build_property_setter_name
+ (PROPERTY_NAME (x)));
+
+ /* Now we check that the appropriate setter is declared,
+ and if not, we declare on ourselves. */
+ {
+ tree setter_decl = lookup_method (CLASS_NST_METHODS (klass),
+ PROPERTY_SETTER_NAME (x));
+
+ if (setter_decl)
+ {
+ /* TODO: Check that the declaration is consistent with the property. */
+ ;
+ }
+ else
+ {
+ /* The setter name is something like 'setName:'.
+ We need the substring 'setName' to build the
+ method declaration due to how the declaration
+ works. TODO: build_method_decl() will then
+ generate back 'setName:' from 'setName'; it
+ would be more efficient to hook into
+ there. */
+ const char *full_setter_name = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x));
+ size_t length = strlen (full_setter_name);
+ char *setter_name = (char *) alloca (length);
+ tree ret_type, selector, arg_type, arg_name;
+
+ strcpy (setter_name, full_setter_name);
+ setter_name[length - 1] = '\0';
+ ret_type = build_tree_list (NULL_TREE, void_type_node);
+ arg_type = build_tree_list (NULL_TREE, TREE_TYPE (x));
+ arg_name = get_identifier ("_value");
+ selector = objc_build_keyword_decl (get_identifier (setter_name),
+ arg_type, arg_name, NULL);
+ setter_decl = build_method_decl (INSTANCE_METHOD_DECL,
+ ret_type, selector,
+ build_tree_list (NULL_TREE, NULL_TREE),
+ false);
+ objc_add_method (objc_interface_context, setter_decl, false, false);
+ METHOD_PROPERTY_CONTEXT (setter_decl) = x;
+ }
+ }
+
+ /* Note how at this point (once an @interface or @protocol
+ have been processed), PROPERTY_GETTER_NAME is always
+ set for all PROPERTY_DECLs, and PROPERTY_SETTER_NAME is
+ always set for all PROPERTY_DECLs where
+ PROPERTY_READONLY == 0. Any time we deal with a getter
+ or setter, we should get the PROPERTY_DECL and use
+ PROPERTY_GETTER_NAME and PROPERTY_SETTER_NAME to know
+ the correct names. */
}
- else if (PROPERTY_SETTER_NAME (x))
- warning (0, "setter = %qs may not be specified in an interface",
- IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (x)));
- if (PROPERTY_IVAR_NAME (x))
- warning (0, "ivar = %qs attribute may not be specified in an interface",
- IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (x)));
}
+ break;
}
+ default:
+ gcc_unreachable ();
+ break;
}
}
@@ -11184,11 +11225,11 @@ objc_diagnose_private_ivar (tree id)
/* Look up ID as an instance variable. OTHER contains the result of
the C or C++ lookup, which we may want to use instead. */
-/* Also handle use of property as setter/getter. */
+/* To use properties inside an instance method, use self.property. */
tree
objc_lookup_ivar (tree other, tree id)
{
- tree ivar, property;
+ tree ivar;
/* If we are not inside of an ObjC method, ivar lookup makes no sense. */
if (!objc_method_context)
@@ -11204,18 +11245,11 @@ objc_lookup_ivar (tree other, tree id)
&& other && other != error_mark_node)
return other;
- property = NULL_TREE;
- if (objc_implementation_context)
- property = is_property (objc_implementation_context, id);
-
- if (!property)
- {
- /* Look up the ivar, but do not use it if it is not accessible. */
- ivar = is_ivar (objc_ivar_chain, id);
-
- if (!ivar || is_private (ivar))
- return other;
- }
+ /* Look up the ivar, but do not use it if it is not accessible. */
+ ivar = is_ivar (objc_ivar_chain, id);
+
+ if (!ivar || is_private (ivar))
+ return other;
/* In an instance method, a local variable (or parameter) may hide the
instance variable. */
@@ -11227,17 +11261,11 @@ objc_lookup_ivar (tree other, tree id)
&& !DECL_FILE_SCOPE_P (other))
#endif
{
- if (property)
- warning (0, "local declaration of %qE hides property", id);
- else
- warning (0, "local declaration of %qE hides instance variable", id);
+ warning (0, "local declaration of %qE hides instance variable", id);
return other;
}
- if (property)
- return build_property_reference (property, id);
-
/* At this point, we are either in an instance method with no obscuring
local definitions, or in a class method with no alternate definitions
at all. */
@@ -11263,31 +11291,77 @@ objc_rewrite_function_call (tree function, tree first_param)
return function;
}
-/* Look for the special case of OBJC_TYPE_REF with the address of
- a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend or one
- of its cousins). */
+/* This is called to "gimplify" a PROPERTY_REF node. It builds the
+ corresponding 'getter' function call. Note that we assume the
+ PROPERTY_REF to be valid since we generated it while parsing. */
+static void
+objc_gimplify_property_ref (tree *expr_p)
+{
+ tree object_expression = PROPERTY_REF_OBJECT (*expr_p);
+ tree property_decl = PROPERTY_REF_PROPERTY_DECL (*expr_p);
+ tree call_exp, getter;
+
+ /* TODO: Implement super.property. */
+
+ getter = objc_finish_message_expr (object_expression,
+ PROPERTY_GETTER_NAME (property_decl),
+ NULL_TREE);
+ call_exp = getter;
+#ifdef OBJCPLUS
+ /* In C++, a getter which returns an aggregate value results in a
+ target_expr which initializes a temporary to the call
+ expression. */
+ if (TREE_CODE (getter) == TARGET_EXPR)
+ {
+ gcc_assert (MAYBE_CLASS_TYPE_P (TREE_TYPE (getter)));
+ gcc_assert (TREE_CODE (TREE_OPERAND (getter, 0)) == VAR_DECL);
+ call_exp = TREE_OPERAND (getter, 1);
+ }
+#endif
+ gcc_assert (TREE_CODE (call_exp) == CALL_EXPR);
+
+ *expr_p = call_exp;
+}
+/* This is called when "gimplifying" the trees. We need to gimplify
+ the Objective-C/Objective-C++ specific trees, then hand over the
+ process to C/C++. */
int
objc_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
{
- enum gimplify_status r0, r1;
- if (TREE_CODE (*expr_p) == OBJ_TYPE_REF
- && TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
- == FUNCTION_DECL)
+ enum tree_code code = TREE_CODE (*expr_p);
+ switch (code)
{
- /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
- value of the OBJ_TYPE_REF, so force them to be emitted
- during subexpression evaluation rather than after the
- OBJ_TYPE_REF. This permits objc_msgSend calls in Objective
- C to use direct rather than indirect calls when the
- object expression has a postincrement. */
- r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, NULL,
- is_gimple_val, fb_rvalue);
- r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
- is_gimple_val, fb_rvalue);
-
- return MIN (r0, r1);
+ /* Look for the special case of OBJC_TYPE_REF with the address
+ of a function in OBJ_TYPE_REF_EXPR (presumably objc_msgSend
+ or one of its cousins). */
+ case OBJ_TYPE_REF:
+ if (TREE_CODE (OBJ_TYPE_REF_EXPR (*expr_p)) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (OBJ_TYPE_REF_EXPR (*expr_p), 0))
+ == FUNCTION_DECL)
+ {
+ enum gimplify_status r0, r1;
+
+ /* Postincrements in OBJ_TYPE_REF_OBJECT don't affect the
+ value of the OBJ_TYPE_REF, so force them to be emitted
+ during subexpression evaluation rather than after the
+ OBJ_TYPE_REF. This permits objc_msgSend calls in
+ Objective C to use direct rather than indirect calls when
+ the object expression has a postincrement. */
+ r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p, NULL,
+ is_gimple_val, fb_rvalue);
+ r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p, post_p,
+ is_gimple_val, fb_rvalue);
+
+ return MIN (r0, r1);
+ }
+ break;
+ case PROPERTY_REF:
+ objc_gimplify_property_ref (expr_p);
+ /* Do not return yet; let C/C++ gimplify the resulting expression. */
+ break;
+ default:
+ break;
}
#ifdef OBJCPLUS
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 2456c109009..95e90703c5a 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -54,18 +54,64 @@ tree objc_eh_personality (void);
#define METHOD_TYPE_ATTRIBUTES(DECL) ((DECL)->decl_common.abstract_origin)
#define METHOD_PROPERTY_CONTEXT(DECL) ((DECL)->decl_common.size_unit)
-#define PROPERTY_NAME(DECL) ((DECL)->decl_minimal.name)
+
+/* PROPERTY_DECL. A PROPERTY_DECL repesents a @property declaration
+ (when attached to the list of properties of an interface) or a
+ @synthesize or @dynamic declaration (when attached to the list of
+ properties of an implementation). */
+
+/* TREE_TYPE is the type (int, float, etc) of the property. */
+
+/* PROPERTY_NAME is the name of the property. */
+#define PROPERTY_NAME(DECL) DECL_NAME(DECL)
+
+/* PROPERTY_GETTER_NAME is the identifier of the getter method. */
#define PROPERTY_GETTER_NAME(DECL) ((DECL)->decl_non_common.arguments)
+
+/* PROPERTY_SETTER_NAME is the identifier of the setter method. */
#define PROPERTY_SETTER_NAME(DECL) ((DECL)->decl_non_common.result)
-#define PROPERTY_IVAR_NAME(DECL) ((DECL)->decl_common.initial)
-#define PROPERTY_READONLY(DECL) ((DECL)->decl_minimal.context)
-#define PROPERTY_COPIES(DECL) ((DECL)->decl_common.size_unit)
-enum objc_property_assign_semantics {
+/* PROPERTY_READONLY can be 0 or 1. */
+#define PROPERTY_READONLY(DECL) DECL_LANG_FLAG_0 (DECL)
+
+/* PROPERTY_NONATOMIC can be 0 or 1. */
+#define PROPERTY_NONATOMIC(DECL) DECL_LANG_FLAG_1 (DECL)
+
+typedef enum objc_property_assign_semantics {
OBJC_PROPERTY_ASSIGN = 1,
OBJC_PROPERTY_RETAIN = 2,
OBJC_PROPERTY_COPY = 3
-};
+} objc_property_assign_semantics;
+
+/* PROPERTY_ASSIGN_SEMANTICS can be OBJC_PROPERTY_ASSIGN,
+ OBJC_PROPERTY_RETAIN or OBJC_PROPERTY_COPY. We need an integer to
+ store it, so we hijack the alignment, that properties don't
+ have. */
+#define PROPERTY_ASSIGN_SEMANTICS(DECL) ((DECL)->decl_common.align)
+
+/* PROPERTY_IVAR_NAME is the identifier of the instance variable.
+ This is set only if the PROPERTY_DECL represents a @synthesize;
+ otherwise, it is set to TREE_NULL. */
+#define PROPERTY_IVAR_NAME(DECL) ((DECL)->decl_common.initial)
+
+/* PROPERTY_DYNAMIC can be 0 or 1. This is 1 if the PROPERTY_DECL
+ represents a @dynamic (or if it is a @property for which a @dynamic
+ declaration has been parsed); otherwise, it is set to 0. */
+#define PROPERTY_DYNAMIC(DECL) DECL_LANG_FLAG_2 (DECL)
+
+
+/* PROPERTY_REF. A PROPERTY_REF represents an 'object.property'
+ expression. */
+
+/* PROPERTY_REF_OBJECT is the object whose property we are
+ accessing. */
+#define PROPERTY_REF_OBJECT(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 0)
+
+/* PROPERTY_REF_PROPERTY_DECL is the PROPERTY_DECL for the property
+ used in the expression. From it, you can get the property type,
+ and the getter/setter names. */
+#define PROPERTY_REF_PROPERTY_DECL(NODE) TREE_OPERAND (PROPERTY_REF_CHECK (NODE), 1)
+
/* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
diff --git a/gcc/objc/objc-tree.def b/gcc/objc/objc-tree.def
index b56734789d8..5da2671c79e 100644
--- a/gcc/objc/objc-tree.def
+++ b/gcc/objc/objc-tree.def
@@ -40,6 +40,24 @@ DEFTREECODE (PROPERTY_DECL, "property_decl", tcc_declaration, 0)
DEFTREECODE (MESSAGE_SEND_EXPR, "message_send_expr", tcc_expression, 3)
DEFTREECODE (CLASS_REFERENCE_EXPR, "class_reference_expr", tcc_expression, 1)
+/* This tree is used to represent the expression 'object.property',
+ where 'object' is an Objective-C object and 'property' is an
+ Objective-C property. Operand 0 is the object (the tree
+ representing the expression), and Operand 1 is the property (the
+ PROPERTY_DECL). A PROPERTY_REF tree needs to be transformed into
+ 'setter' and 'getter' calls at some point; at the moment this
+ happens in two places:
+
+ * if we detect that a modify expression is being applied to a
+ PROPERTY_REF, then we transform that into a 'getter' call (this
+ happens in build_modify_expr() or cp_build_modify_expr()).
+
+ * else, it will remain as a PROPERTY_REF until we get to
+ gimplification; at that point, we convert each PROPERTY_REF into
+ a 'getter' call during ObjC/ObjC++ gimplify.
+*/
+DEFTREECODE (PROPERTY_REF, "property_ref", tcc_expression, 2)
+
/*
Local variables:
mode:c
diff --git a/gcc/recog.c b/gcc/recog.c
index 3ab72f10dd3..1a4824a5f9b 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -2868,15 +2868,8 @@ split_all_insns (void)
}
else
{
- rtx last = split_insn (insn);
- if (last)
+ if (split_insn (insn))
{
- /* The split sequence may include barrier, but the
- BB boundary we are interested in will be set to
- previous one. */
-
- while (BARRIER_P (last))
- last = PREV_INSN (last);
SET_BIT (blocks, bb->index);
changed = true;
}
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 9096d8385dd..c8f56f5470b 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -776,6 +776,10 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
/* Second pass evaluates arguments. */
+ /* Make sure stack is consistent for asm goto. */
+ if (nlabels > 0)
+ do_pending_stack_adjust ();
+
ninout = 0;
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
{
diff --git a/gcc/target.def b/gcc/target.def
index cc69c9193d4..98cea58c40d 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1982,6 +1982,26 @@ DEFHOOK
int, (tree fundecl, tree funtype, int size),
default_return_pops_args)
+/* Return a mode wide enough to copy any function value that might be
+ returned. */
+DEFHOOK
+(get_raw_result_mode,
+ "This target hook returns the mode to be used when accessing raw return\
+ registers in @code{__builtin_return}. Define this macro if the value\
+ in @var{reg_raw_mode} is not correct.",
+ enum machine_mode, (int regno),
+ default_get_reg_raw_mode)
+
+/* Return a mode wide enough to copy any argument value that might be
+ passed. */
+DEFHOOK
+(get_raw_arg_mode,
+ "This target hook returns the mode to be used when accessing raw argument\
+ registers in @code{__builtin_apply_args}. Define this macro if the value\
+ in @var{reg_raw_mode} is not correct.",
+ enum machine_mode, (int regno),
+ default_get_reg_raw_mode)
+
HOOK_VECTOR_END (calls)
/* Return the diagnostic message string if conversion from FROMTYPE
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index b6aefdbe58f..22bba3b33bc 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
#include "target-def.h"
#include "ggc.h"
#include "hard-reg-set.h"
+#include "regs.h"
#include "reload.h"
#include "optabs.h"
#include "recog.h"
@@ -1333,6 +1334,15 @@ sjlj_except_unwind_info (void)
return UI_SJLJ;
}
+/* To be used by targets where reg_raw_mode doesn't return the right
+ mode for registers used in apply_builtin_return and apply_builtin_arg. */
+
+enum machine_mode
+default_get_reg_raw_mode(int regno)
+{
+ return reg_raw_mode[regno];
+}
+
const struct default_options empty_optimization_table[] =
{
{ OPT_LEVELS_NONE, 0, NULL, 0 }
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index e89ac8ec432..87625137de3 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -168,4 +168,6 @@ extern int default_loop_align_max_skip (rtx);
extern int default_label_align_max_skip (rtx);
extern int default_jump_align_max_skip (rtx);
+extern enum machine_mode default_get_reg_raw_mode(int);
+
extern const struct default_options empty_optimization_table[];
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 23174143ea6..01a3fcb9239 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,131 @@
+2010-10-31 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/46142
+ * gcc.target/i386/fma3-builtin-2.c: Add -mtune=generic.
+ * gcc.target/i386/fma4-builtin-2.c: Likewise.
+
+2010-10-31 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.dg/stack-usage-1.c (SIZE): Increase to 248 for some MIPS targets.
+
+2010-10-31 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.dg/tls/thr-init-1.c: Fix order of dg-do.
+ * gcc.dg/tls/thr-init-2.c: Likewise. Require tls_runtime rather
+ than tls.
+ * gcc.dg/torture/tls/thr-init-1.c: Require tls_runtime rather than tls.
+ * gcc.dg/torture/tls/thr-init-2.c: Likewise.
+ * objc.dg/torture/tls/thr-init.m: Likewise.
+ * objc.dg/torture/tls/thr-init-2.m: Likewise.
+ * objc.dg/torture/tls/thr-init-3.m: Likewise.
+
+2010-10-31 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.c-torture/execute/20101011-1.c: Skip for MIPS unless running
+ the Linux kernel.
+
+2010-10-30 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44917
+ PR fortran/44926
+ PR fortran/46196
+ * gfortran.dg/typebound_generic_10.f03: New.
+
+2010-10-30 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ Implemented Objective-C 2.0 @property, @synthesize and @dynamic.
+ * objc.dg/property/property-neg-1.m: Updated for changes in the
+ syntax of @property and the implementation of
+ @synthesize/@dynamic.
+ * objc.dg/property/property-neg-2.m: Same change.
+ * objc.dg/property/property-neg-3.m: Same change.
+ * objc.dg/property/property-neg-4.m: Same change.
+ * objc.dg/property/property-neg-5.m: Same change.
+ * objc.dg/property/property-neg-7.m: Same change.
+ * objc.dg/property/property-1.m: Same change.
+ * objc.dg/property/synthesize-1.m: Same change.
+ * objc.dg/property/at-property-2.m: Same change.
+ * objc.dg/property/at-property-4.m: Same change.
+
+ * objc.dg/property/fsf-property-method-acces.m: Updated for
+ changes in the syntax of @property and the implementation of
+ @synthesize/@dynamic. Use the same code for GNU and NeXT runtime.
+ * objc.dg/property/fsf-property-basic.m: Same change.
+ * objc.dg/property/fsf-property-named-ivar.m: Same change.
+
+ * objc.dg/property/at-property-5.m: New.
+ * objc.dg/property/at-property-6.m: New.
+ * objc.dg/property/at-property-7.m: New.
+ * objc.dg/property/at-property-8.m: New.
+ * objc.dg/property/at-property-9.m: New.
+ * objc.dg/property/at-property-10.m: New.
+ * objc.dg/property/at-property-11.m: New.
+ * objc.dg/property/synthesize-2.m: New.
+ * objc.dg/property/dynamic-2.m: New.
+
+ * obj-c++.dg/property/property-neg-1.mm: Updated for changes in the
+ syntax of @property and the implementation of
+ @synthesize/@dynamic.
+ * obj-c++.dg/property/property-neg-2.mm: Same change.
+ * obj-c++.dg/property/property-neg-3.mm: Same change.
+ * obj-c++.dg/property/property-neg-4.mm: Same change.
+ * obj-c++.dg/property/property-neg-5.mm: Same change.
+ * obj-c++.dg/property/property-neg-7.mm: Same change.
+ * obj-c++.dg/property/property-1.mm: Same change.
+ * obj-c++.dg/property/synthesize-1.mm: Same change.
+ * obj-c++.dg/property/at-property-2.mm: Same change.
+ * obj-c++.dg/property/at-property-4.mm: Same change.
+
+ * obj-c++.dg/property/fsf-property-method-acces.mm: Updated for
+ changes in the syntax of @property and the implementation of
+ @synthesize/@dynamic. Use the same code for GNU and NeXT runtime.
+ * obj-c++.dg/property/fsf-property-basic.mm: Same change.
+ * obj-c++.dg/property/fsf-property-named-ivar.mm: Same change.
+
+ * obj-c++.dg/property/at-property-5.mm: New.
+ * obj-c++.dg/property/at-property-6.mm: New.
+ * obj-c++.dg/property/at-property-7.mm: New.
+ * obj-c++.dg/property/at-property-8.mm: New.
+ * obj-c++.dg/property/at-property-9.mm: New.
+ * obj-c++.dg/property/at-property-10.mm: New.
+ * obj-c++.dg/property/at-property-11.mm: New.
+ * obj-c++.dg/property/synthesize-2.mm: New.
+ * obj-c++.dg/property/dynamic-2.mm: New.
+
+2010-10-29 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
+ Andrew Pinski <pinskia@gmail.com>
+
+ * gcc.c-torture/execute/vector-shift.c: New testcase.
+ * gcc.c-torture/execute/vector-shift1.c: Likewise.
+ * gcc.c-torture/execute/vector-shift2.c: Likewise.
+ * gcc.dg/vector-shift.c: Likewise.
+ * gcc.dg/vector-shift1.c: Likewise.
+ * gcc.dg/torture/vector-shift2.c: Likewise.
+ * gcc.dg/vector-shift3.c: Likewise.
+ * gcc.dg/simd-1b.c: Adjust.
+
+2010-10-29 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * gcc.c-torture/execute/20101011-1.c: Skip on SH.
+
+2010-10-29 Pat Haugen <pthaugen@us.ibm.com>
+
+ * gcc.c-torture/execute/20101011-1.c: Fix #ifdef.
+
+2010-10-28 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/46153
+ * gcc.target/i386/pr46153.c: New test.
+
+2010-10-27 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/constexpr-is_literal.C: New.
+
+2010-10-27 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/46161
+ * gfortran.dg/class_dummy_3.f03: New.
+
2010-10-27 H.J. Lu <hongjiu.lu@intel.com>
* gcc.target/i386/avx-vzeroupper-1.c: Add -mtune=generic.
@@ -24,16 +152,16 @@
updates in warning.
* obj-c++.dg/property/property-neg-5.mm: Updated testcase for
updates in warning.
-
+
2010-10-27 Nicola Pero <nicola.pero@meta-innovation.com>
- * objc.dg/property/at-property-1.m: New.
+ * objc.dg/property/at-property-1.m: New.
* objc.dg/property/at-property-2.m: New.
* objc.dg/property/at-property-3.m: New.
* objc.dg/ivar-invalid-type-1.m: New.
* obj-c++.dg/property/at-property-1.mm: New.
* obj-c++.dg/property/at-property-2.mm: New.
- * obj-c++.dg/property/at-property-3.mm: New.
+ * obj-c++.dg/property/at-property-3.mm: New.
* obj-c++.dg/ivar-invalid-type-1.mm: New.
* objc.dg/property/property-neg-6.m: Updated testcase for updates
in error reporting.
@@ -163,8 +291,8 @@
2010-10-24 Nicola Pero <nicola.pero@meta-innovation.com>
- PR objc/45735
- * obj-c.dg/pr45735.mm: New.
+ PR objc/45735
+ * obj-c.dg/pr45735.mm: New.
* obj-c++.dg/pr45735.mm: New.
2010-10-24 Nicola Pero <nicola.pero@meta-innovation.com>
@@ -185,10 +313,10 @@
parameter attributes are now supported.
* obj-c++.dg/attributes/method-attribute-2.m: Same change.
* objc.dg/attributes/parameter-attribute-1.m: New test.
- * objc.dg/attributes/parameter-attribute-2.m: New test.
+ * objc.dg/attributes/parameter-attribute-2.m: New test.
* obj-c++.dg/attributes/parameter-attribute-1.m: New test.
- * obj-c++.dg/attributes/parameter-attribute-2.m: New test.
-
+ * obj-c++.dg/attributes/parameter-attribute-2.m: New test.
+
2010-10-23 Iain Sandoe <iains@gcc.gnu.org>
Based on the CFString implementation in FSF apple/trunk branch.
@@ -204,7 +332,7 @@
* objc.dg/demangle-1.m: New test.
* obj-c++.dg/demangle-1.mm: New test.
* obj-c++.dg/demangle-2.mm: New test.
- * obj-c++.dg/demangle-3.mm: New test.
+ * obj-c++.dg/demangle-3.mm: New test.
2010-10-23 Ian Lance Taylor <iant@google.com>
diff --git a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
index 4c36ad3e5cf..077940548e1 100644
--- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
@@ -9,6 +9,15 @@
#elif defined (__SPU__)
/* On SPU division by zero does not trap. */
# define DO_TEST 0
+#elif defined (__sh__)
+ /* On SH division by zero does not trap. */
+# define DO_TEST 0
+#elif defined (__mips__) && !defined(__linux__)
+ /* MIPS divisions do trap by default, but libgloss targets do not
+ intercept the trap and raise a SIGFPE. The same is probably
+ true of other bare-metal environments, so restrict the test to
+ systems that use the Linux kernel. */
+# define DO_TEST 0
#else
# define DO_TEST 1
#endif
@@ -35,7 +44,7 @@ int k;
int
main ()
{
-#ifdef DO_TEST
+#if DO_TEST
signal (SIGFPE, sigfpe);
k = i / j;
abort ();
diff --git a/gcc/testsuite/gcc.c-torture/execute/vector-shift.c b/gcc/testsuite/gcc.c-torture/execute/vector-shift.c
new file mode 100644
index 00000000000..f52eb58a1b9
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vector-shift.c
@@ -0,0 +1,48 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+ typeof(result) result1 = result; \
+ if(sizeof (result1) != sizeof (expected)) \
+ __builtin_abort (); \
+ if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+ __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+ vector int result;
+ TEST ((numbers << allzeros), numbers);
+ TEST ((numbers >> allzeros), numbers);
+ TEST((numbers << allones), numbersleftshiftallones);
+ TEST((numbers >> allones), numbersrightshiftallones);
+ /* Test left shift followed by a right shift, numbers should be back as
+ numbers are all small numbers and no lose of precision happens. */
+ TEST((numbers << allones) >> allones, numbers);
+
+
+
+ TEST ((unumbers << uallzeros), unumbers);
+ TEST ((unumbers >> uallzeros), unumbers);
+ TEST((unumbers << uallones), unumbersleftshiftallones);
+ TEST((unumbers >> uallones), unumbersrightshiftallones);
+ /* Test left shift followed by a right shift, numbers should be back as
+ numbers are all small numbers and no lose of precision happens. */
+ TEST((unumbers << uallones) >> uallones, unumbers);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/vector-shift1.c b/gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
new file mode 100644
index 00000000000..6041fc3b07e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
@@ -0,0 +1,17 @@
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+ vector short v0 = {argc,2,3,4,5,6,7};
+ vector short v1 = {2,2,2,2,2,2,2};
+ vector short r1,r2,r3,r4;
+ int i = 8;
+
+ r1 = v0 << 1;
+ r2 = v0 >> 1;
+
+ r3 = v0 << v1;
+ r4 = v0 >> v1;
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/vector-shift2.c b/gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
new file mode 100644
index 00000000000..55f10355522
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
@@ -0,0 +1,59 @@
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+ vector(4, uint) vuint = { 1, 2, 3, 4};
+ vector(4, int) vint0 = { 1, 1, 1, 1};
+ vector(4, int) vint1 = {-1, -1, -1, -1};
+
+ vector(4, int) i1, i2, i3;
+ vector(4, uint) u1, u2, u3;
+
+ i1 = vint1<< vint0;
+
+ if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+ __builtin_abort ();
+ if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+ __builtin_abort ();
+ if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+ __builtin_abort ();
+ if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+ __builtin_abort ();
+
+ u1 = vuint << vint0;
+
+ if (vidx(int, u1, 0) != ((uint)1 << (int)1))
+ __builtin_abort ();
+ if (vidx(int, u1, 1) != ((uint)2 << (int)1))
+ __builtin_abort ();
+ if (vidx(int, u1, 2) != ((uint)3 << (int)1))
+ __builtin_abort ();
+ if (vidx(int, u1, 3) != ((uint)4 << (int)1))
+ __builtin_abort ();
+
+
+ i2 = vint1 >> vuint;
+
+ if (vidx(int, i2, 0) != ((int)-1 >> (uint)1))
+ __builtin_abort ();
+ if (vidx(int, i2, 1) != ((int)-1 >> (uint)2))
+ __builtin_abort ();
+ if (vidx(int, i2, 2) != ((int)-1 >> (uint)3))
+ __builtin_abort ();
+ if (vidx(int, i2, 3) != ((int)-1 >> (uint)4))
+ __builtin_abort ();
+
+
+ vint1 >>= vuint;
+
+ vuint <<= vint0;
+ vuint <<= vint1;
+
+
+ return 0;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/simd-1b.c b/gcc/testsuite/gcc.dg/simd-1b.c
index 1e2b597b565..44c39c2ef96 100644
--- a/gcc/testsuite/gcc.dg/simd-1b.c
+++ b/gcc/testsuite/gcc.dg/simd-1b.c
@@ -18,8 +18,8 @@ hanneke ()
c &= d;
a |= b;
c ^= d;
- a >>= b; /* { dg-error "invalid operands to binary >>" } */
- c <<= d; /* { dg-error "invalid operands to binary <<" } */
+ a >>= b;
+ c <<= d;
a = +b;
c = ~d;
diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c
index 25ae9a906ac..befe4cbc137 100644
--- a/gcc/testsuite/gcc.dg/stack-usage-1.c
+++ b/gcc/testsuite/gcc.dg/stack-usage-1.c
@@ -24,7 +24,12 @@
#elif defined (__ia64__)
# define SIZE 272
#elif defined(__mips__)
-# define SIZE 240
+# if defined (__mips_abicalls) \
+ || (defined _MIPS_SIM && (_MIPS_SIM ==_ABIN32 || _MIPS_SIM==_ABI64))
+# define SIZE 240
+# else
+# define SIZE 248
+# endif
#elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) \
|| defined (__POWERPC__) || defined (PPC) || defined (_IBMR2)
# define SIZE 240
diff --git a/gcc/testsuite/gcc.dg/tls/thr-init-1.c b/gcc/testsuite/gcc.dg/tls/thr-init-1.c
index de273d930aa..eb2f84695fb 100644
--- a/gcc/testsuite/gcc.dg/tls/thr-init-1.c
+++ b/gcc/testsuite/gcc.dg/tls/thr-init-1.c
@@ -1,5 +1,5 @@
-/* { dg-require-effective-target tls } */
/* { dg-do compile } */
+/* { dg-require-effective-target tls } */
static __thread int fstat ;
static __thread int fstat = 1 ;
diff --git a/gcc/testsuite/gcc.dg/tls/thr-init-2.c b/gcc/testsuite/gcc.dg/tls/thr-init-2.c
index ebc512f77a5..22c96ea9f63 100644
--- a/gcc/testsuite/gcc.dg/tls/thr-init-2.c
+++ b/gcc/testsuite/gcc.dg/tls/thr-init-2.c
@@ -1,5 +1,5 @@
-/* { dg-require-effective-target tls } */
/* { dg-do run } */
+/* { dg-require-effective-target tls_runtime } */
/* { dg-add-options tls } */
extern void abort() ;
diff --git a/gcc/testsuite/gcc.dg/torture/tls/thr-init-1.c b/gcc/testsuite/gcc.dg/torture/tls/thr-init-1.c
index 76dc62a7adc..ff3338ffbe5 100644
--- a/gcc/testsuite/gcc.dg/torture/tls/thr-init-1.c
+++ b/gcc/testsuite/gcc.dg/torture/tls/thr-init-1.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-require-effective-target tls } */
+/* { dg-require-effective-target tls_runtime } */
/* { dg-add-options tls } */
extern int printf (char *,...);
diff --git a/gcc/testsuite/gcc.dg/torture/tls/thr-init-2.c b/gcc/testsuite/gcc.dg/torture/tls/thr-init-2.c
index bef1d287e85..44156232cf3 100644
--- a/gcc/testsuite/gcc.dg/torture/tls/thr-init-2.c
+++ b/gcc/testsuite/gcc.dg/torture/tls/thr-init-2.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-require-effective-target tls } */
+/* { dg-require-effective-target tls_runtime } */
/* { dg-add-options tls } */
extern int printf (char *,...);
diff --git a/gcc/testsuite/gcc.dg/torture/vector-shift2.c b/gcc/testsuite/gcc.dg/torture/vector-shift2.c
new file mode 100644
index 00000000000..a4ca9240058
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vector-shift2.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1 1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+ vector(16, uchar) vuchar = { ch14, ch14, ch14, ch14};
+ vector(16, char) vchar0 = { ch1, ch1, ch1, ch1};
+ vector(16, char) vchar1 = { chm1, chm1, chm1, chm1};
+
+ vector(16, char) i1, i2, i3;
+ vector(16, uchar) u1, u2, u3;
+
+ i1 = vchar1<< vchar0;
+
+ if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+ __builtin_abort ();
+ if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+ __builtin_abort ();
+ if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+ __builtin_abort ();
+ if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+ __builtin_abort ();
+ u1 = vuchar << vchar0;
+
+ if (vidx(char, u1, 0) != ((uchar)1 << (char)1))
+ __builtin_abort ();
+ if (vidx(char, u1, 1) != ((uchar)2 << (char)1))
+ __builtin_abort ();
+ if (vidx(char, u1, 2) != ((uchar)3 << (char)1))
+ __builtin_abort ();
+ if (vidx(char, u1, 3) != ((uchar)4 << (char)1))
+ __builtin_abort ();
+
+
+ i2 = vchar1 >> vuchar;
+
+ if (vidx(char, i2, 0) != ((char)-1 >> (uchar)1))
+ __builtin_abort ();
+ if (vidx(char, i2, 1) != ((char)-1 >> (uchar)2))
+ __builtin_abort ();
+ if (vidx(char, i2, 2) != ((char)-1 >> (uchar)3))
+ __builtin_abort ();
+ if (vidx(char, i2, 3) != ((char)-1 >> (uchar)4))
+ __builtin_abort ();
+
+ vchar1 >>= vuchar;
+ vuchar <<= vchar0;
+ vuchar <<= vchar1;
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/vector-shift.c b/gcc/testsuite/gcc.dg/vector-shift.c
new file mode 100644
index 00000000000..f2b12ba73f6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vector-shift.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+ vector(4,char) vchar = {1,2,3,4};
+ vector(4, int) vint = {1,1,1,1};
+
+ vint <<= vchar; /* { dg-error "nvalid operands to binary <<" } */
+ vchar >>= vint; /* { dg-error "nvalid operands to binary >>" } */
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/vector-shift1.c b/gcc/testsuite/gcc.dg/vector-shift1.c
new file mode 100644
index 00000000000..51bc0ad3989
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vector-shift1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+ vector(4, float) vfloat0 = {1., 2., 3., 4.};
+ vector(4, float) vfloat1 = {1., 2., 3., 4.};
+
+ vector(4, int) vint = {1, 1, 1, 1 };
+
+ vint <<= vfloat0; /* { dg-error "nvalid operands to binary <<" } */
+ vfloat0 >>= vint; /* { dg-error "nvalid operands to binary >>" } */
+
+ vfloat0 <<= vfloat1; /* { dg-error "nvalid operands to binary <<" } */
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/vector-shift3.c b/gcc/testsuite/gcc.dg/vector-shift3.c
new file mode 100644
index 00000000000..38a9843d117
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vector-shift3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+
+int main (int argc, char *argv[]) {
+ vector(8, short) v0 = {argc,2,3,4,5,6,7};
+ short sc;
+
+
+ scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/fma3-builtin-2.c b/gcc/testsuite/gcc.target/i386/fma3-builtin-2.c
index b84e4a0b3ec..01768b9638f 100644
--- a/gcc/testsuite/gcc.target/i386/fma3-builtin-2.c
+++ b/gcc/testsuite/gcc.target/i386/fma3-builtin-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -mfma -mno-fma4" } */
+/* { dg-options "-O3 -mfma -mno-fma4 -mtune=generic" } */
#ifndef SIZE
#define SIZE 1024
diff --git a/gcc/testsuite/gcc.target/i386/fma4-builtin-2.c b/gcc/testsuite/gcc.target/i386/fma4-builtin-2.c
index a7e3975719f..18927bc09d4 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-builtin-2.c
+++ b/gcc/testsuite/gcc.target/i386/fma4-builtin-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -mfma4" } */
+/* { dg-options "-O3 -mfma4 -mtune=generic" } */
#ifndef SIZE
#define SIZE 1024
diff --git a/gcc/testsuite/gcc.target/i386/pr46153.c b/gcc/testsuite/gcc.target/i386/pr46153.c
new file mode 100644
index 00000000000..c6e0f52e894
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr46153.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-msse -ffloat-store" } */
+
+typedef float v4sf __attribute__ ((__vector_size__ (16)));
+
+v4sf foo (v4sf a)
+{
+ return __builtin_ia32_movlhps (a, a);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr46226.c b/gcc/testsuite/gcc.target/i386/pr46226.c
new file mode 100644
index 00000000000..389158a03ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr46226.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-Os -fomit-frame-pointer -mno-accumulate-outgoing-args -fno-asynchronous-unwind-tables" } */
+
+extern void abort(void);
+
+static void *p[2];
+
+void __attribute__((noinline))
+g(int x, ...)
+{
+ asm volatile ("" : : "g"(x));
+}
+
+void __attribute__((noinline))
+f(int x)
+{
+ p[0] = __builtin_return_address (0);
+ if (x == 0)
+ g(0);
+ g(1, 2, 3, 4, 5, 6, 7);
+
+ asm goto ("jmp %l0" : : : : label);
+ abort ();
+
+ label:
+ p[1] = __builtin_return_address (0);
+}
+
+int main()
+{
+ f(1);
+ if (p[0] != p[1])
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/class_dummy_3.f03 b/gcc/testsuite/gfortran.dg/class_dummy_3.f03
new file mode 100644
index 00000000000..6b12eb892b0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_dummy_3.f03
@@ -0,0 +1,30 @@
+! { dg-do compile }
+!
+! PR 46161: [OOP] Invalid: Passing non-polymorphic to allocatable polymorphic dummy
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+ implicit none
+
+ type :: base
+ end type
+
+ type, extends(base) :: ext
+ end type
+
+ type(base), allocatable :: a
+ class(base), pointer :: b
+ class(ext), allocatable :: c
+
+ call test(a) ! { dg-error "must be polymorphic" }
+ call test(b) ! { dg-error "must be ALLOCATABLE" }
+ call test(c) ! { dg-error "must have the same declared type" }
+
+contains
+
+ subroutine test(arg)
+ implicit none
+ class(base), allocatable :: arg
+ end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/typebound_generic_10.f03 b/gcc/testsuite/gfortran.dg/typebound_generic_10.f03
new file mode 100644
index 00000000000..590fa5278ab
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/typebound_generic_10.f03
@@ -0,0 +1,32 @@
+! { dg-do compile }
+!
+! PR 49196: [OOP] gfortran compiles invalid generic TBP: dummy arguments are type compatible
+!
+! Contributed by Hans-Werner Boschmann <boschmann@tp1.physik.uni-siegen.de>
+
+module generic
+
+ type :: a_type
+ contains
+ procedure :: a_subroutine
+ end type a_type
+
+ type,extends(a_type) :: b_type
+ contains
+ procedure :: b_subroutine
+ generic :: g_sub => a_subroutine,b_subroutine ! { dg-error "are ambiguous" }
+ end type b_type
+
+contains
+
+ subroutine a_subroutine(this)
+ class(a_type)::this
+ end subroutine a_subroutine
+
+ subroutine b_subroutine(this)
+ class(b_type)::this
+ end subroutine b_subroutine
+
+end module generic
+
+! { dg-final { cleanup-modules "generic" } }
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-10.mm b/gcc/testsuite/obj-c++.dg/property/at-property-10.mm
new file mode 100644
index 00000000000..f130292bb0f
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-10.mm
@@ -0,0 +1,100 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax in a number of expressions. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int
+test (int g)
+{
+ return g;
+}
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+ MyRootClass *object2 = [[MyRootClass alloc] init];
+
+ object.a = 14;
+ object.a = object.a + object.a;
+
+ if (object.a != 28)
+ abort ();
+
+ object.a = 99;
+ /* TODO: The following one does not work yet. */
+ /* object.a++; */
+ object.a = object.a + 1;
+
+ if (object.a != 100)
+ abort ();
+
+ object.a = 99;
+ object.a *= 2;
+
+ if (object.a != 198)
+ abort ();
+
+ {
+ int f = object.a;
+
+ if (f != 198)
+ abort ();
+
+ if (f != object.a)
+ abort ();
+
+ if (object.a != f)
+ abort ();
+
+ object.a = object.a;
+
+ if (object.a != 198)
+ abort ();
+ }
+
+ if (test (object.a) != 198)
+ abort ();
+
+ object.a = -object.a;
+
+ if (object.a != -198)
+ abort ();
+
+ /* TODO: The following one does not work yet. */
+ /* for (object.a = 0; object.a < 99; object.a++) */
+ for (object.a = 0; object.a < 99; object.a = object.a + 1)
+ object2.a = object.a;
+
+ if (object2.a != object.a - 1)
+ abort ();
+
+ if (object2.a != 98)
+ abort ();
+
+ if (object.a != 99)
+ abort ();
+
+ return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-11.mm b/gcc/testsuite/obj-c++.dg/property/at-property-11.mm
new file mode 100644
index 00000000000..36da7bf2794
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-11.mm
@@ -0,0 +1,43 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test that properties are found even if implemented in superclasses. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+@interface MySubClass : MyRootClass
+@end
+
+@implementation MySubClass
+@end
+
+int main (void)
+{
+ MySubClass *object = [[MySubClass alloc] init];
+
+ object.a = 40;
+ if (object.a != 40)
+ abort ();
+
+ return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-2.mm b/gcc/testsuite/obj-c++.dg/property/at-property-2.mm
index 7442251377a..a97c33ea874 100644
--- a/gcc/testsuite/obj-c++.dg/property/at-property-2.mm
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-2.mm
@@ -6,8 +6,8 @@
{
Class isa;
}
-@property id name __attribute__((deprecated));
-@property id table __attribute__((xxx)); /* { dg-warning ".xxx. attribute directive ignored" } */
+@property int name __attribute__((deprecated));
+@property int table __attribute__((xxx)); /* { dg-warning ".xxx. attribute directive ignored" } */
@property void function (void); /* { dg-error "can.t make .function. into a method" } */
@property typedef int j; /* { dg-error "invalid type for property" } */
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
index 05223a3fa22..e327930f87b 100644
--- a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm
@@ -6,36 +6,35 @@
{
Class isa;
}
-- (id) myGetter;
-- (id) myGetterB;
-- (void) mySetter: (id)property;
-- (void) mySetterB: (id)property;
+- (int) myGetter;
+- (int) myGetterB;
+- (int) myGetter2;
+- (void) mySetter: (int)property;
+- (void) mySetterB: (int)property;
+- (void) mySetter2: (int)property;
/* Test that all the new property attributes can be parsed. */
@property (assign) id property_a;
@property (copy) id property_b;
-@property (nonatomic) id property_c;
-@property (readonly) id property_d;
-@property (readwrite) id property_e;
+@property (nonatomic) int property_c;
+@property (readonly) int property_d;
+@property (readwrite) int property_e;
@property (retain) id property_f;
-@property (release) id property_g; /* { dg-error "unknown property attribute" } */
+@property (release) int property_g; /* { dg-error "unknown property attribute" } */
-/* The following will be enabled when @synthesized is implemented. */
-/* @property (getter=myGetter) id property_h; */
-/* @property (setter=mySetter:) id property_i; */
+@property (getter=myGetter) int property_h;
+@property (setter=mySetter:) int property_i;
/* Now test various problems. */
@property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */
-/* The following will be enabled when @synthesized is implemented. */
-/* @property (readonly, setter=setA:) int b; */ /* dg-warning ".readonly. attribute conflicts with .setter. attribute" */
+@property (readonly, setter=mySetterB:) int b; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
@property (assign, retain) id c; /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */
@property (assign, copy) id d; /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */
@property (copy, retain) id e; /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */
-/* The following will be enabled when @synthesized is implemented. */
-/* @property (setter=mySetter:,setter=mySetterB:) id f; */ /* dg-error ".setter. attribute may only be specified once" */
-/* @property (getter=myGetter:,getter=myGetterB:) id f; */ /* dg-error ".getter. attribute may only be specified once" */
+@property (setter=mySetter:,setter=mySetter2:) int f; /* { dg-error ".setter. attribute may only be specified once" } */
+@property (getter=myGetter, getter=myGetter2 ) int g; /* { dg-error ".getter. attribute may only be specified once" } */
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-5.mm b/gcc/testsuite/obj-c++.dg/property/at-property-5.mm
new file mode 100644
index 00000000000..1e604e90b16
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-5.mm
@@ -0,0 +1,38 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ id property_a;
+ int property_b;
+ int property_c;
+ int property_d;
+ id property_e;
+ id property_f;
+ id property_g;
+ id property_h;
+}
+
+/* Test various error messages. */
+/* FIXME - there is a problem with the testuite in running the following test. The compiler
+ generates the messages, but the testsuite still complains. */
+/*@property id property_a;*/ /* dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" */
+ /* dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 20 */
+@property int property_b = 4; /* { dg-error "expected" } */
+@property (retain) int property_c; /* { dg-error ".retain. attribute is only valid for Objective-C objects" } */
+@property (copy) int property_d; /* { dg-error ".copy. attribute is only valid for Objective-C objects" } */
+
+@property (retain) id property_e;
+@property (retain) id property_f;
+@property (retain) id property_g;
+@property (retain) id property_h;
+/* FIXME - there is a problem with the testuite in running the following test. The compiler
+ generates the messages, but the testsuite still complains. */
+/*@property (retain) id property_e;*/ /* dg-error "redeclaration of property .property_e." */
+ /* dg-message "originally declared here" "" { target *-*-* } 26 */
+@end
+
+@property id test; /* { dg-error "misplaced .@property. Objective-C.. construct" } */
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-6.mm b/gcc/testsuite/obj-c++.dg/property/at-property-6.mm
new file mode 100644
index 00000000000..3f1f0d3abe0
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-6.mm
@@ -0,0 +1,60 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+ and with standard names. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) a
+{
+ return a;
+}
+- (void) setA: (int)value
+{
+ a = value;
+}
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ if (object.a != 0)
+ abort ();
+
+ object.a = 14;
+
+ if (object.a != 14)
+ abort ();
+
+ object.a = 23;
+
+ if (object.a != 23)
+ abort ();
+
+ object.a = 78;
+
+ if (object.a != 78)
+ abort ();
+
+ return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-7.mm b/gcc/testsuite/obj-c++.dg/property/at-property-7.mm
new file mode 100644
index 00000000000..cae04dee498
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-7.mm
@@ -0,0 +1,57 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+ and with a non-standard name for the getter. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property (getter = getA) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) getA
+{
+ return a;
+}
+- (void) setA: (int)value
+{
+ a = value;
+}
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ object.a = 14;
+
+ if (object.a != 14)
+ abort ();
+
+ object.a = 23;
+
+ if (object.a != 23)
+ abort ();
+
+ object.a = 78;
+
+ if (object.a != 78)
+ abort ();
+
+ return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-8.mm b/gcc/testsuite/obj-c++.dg/property/at-property-8.mm
new file mode 100644
index 00000000000..ec37052989a
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-8.mm
@@ -0,0 +1,57 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+ and with a non-standard name for the setter. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property (setter = writeA:) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) a
+{
+ return a;
+}
+- (void) writeA: (int)value
+{
+ a = value;
+}
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ object.a = 14;
+
+ if (object.a != 14)
+ abort ();
+
+ object.a = 23;
+
+ if (object.a != 23)
+ abort ();
+
+ object.a = 78;
+
+ if (object.a != 78)
+ abort ();
+
+ return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-9.mm b/gcc/testsuite/obj-c++.dg/property/at-property-9.mm
new file mode 100644
index 00000000000..12e9ffde872
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/at-property-9.mm
@@ -0,0 +1,49 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax with synthesized setter/getter
+ and with a non-standard name for the getter and setter. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property (getter = giveMeA, setter = writeA:) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ object.a = 14;
+
+ if (object.a != 14)
+ abort ();
+
+ object.a = 23;
+
+ if (object.a != 23)
+ abort ();
+
+ object.a = 78;
+
+ if (object.a != 78)
+ abort ();
+
+ return (0);
+}
diff --git a/gcc/testsuite/obj-c++.dg/property/dynamic-1.mm b/gcc/testsuite/obj-c++.dg/property/dynamic-1.mm
index d66ef282e01..4e84843c355 100644
--- a/gcc/testsuite/obj-c++.dg/property/dynamic-1.mm
+++ b/gcc/testsuite/obj-c++.dg/property/dynamic-1.mm
@@ -20,11 +20,15 @@
int v3;
int v4;
}
+@property int v1;
+@property int v2;
+@property int v3;
+@property int v4;
@end
@implementation Test
@dynamic; /* { dg-error "expected identifier" } */
@dynamic v1, ; /* { dg-error "expected identifier" } */
-@dynamic v1, v2, v3; /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
-@dynamic v4; /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
+@dynamic v1, v2, v3;
+@dynamic v4;
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm b/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm
new file mode 100644
index 00000000000..acc9374278d
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm
@@ -0,0 +1,46 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+ Class isa;
+}
+@end
+
+@implementation MyRootClass
+@end
+
+@dynamic isa; /* { dg-error "misplaced .@dynamic. Objective-C.. construct" } */
+
+@interface Test : MyRootClass
+{
+ int v1;
+}
+@end
+@implementation Test
+@end
+
+
+@interface Test (Category)
+@end
+@implementation Test (Category)
+@dynamic v1; /* { dg-error ".@dynamic. can not be used in categories" } */
+@end
+
+
+@interface AnotherTest : MyRootClass
+{
+}
+@property int one;
+@end
+
+@implementation AnotherTest
+@dynamic one;
+/* FIXME - there is a problem with the testuite in running the following test. The compiler
+ generates the messages, but the testsuite still complains. */
+/*@dynamic one;*/ /* dg-error "property .one. already specified in .@dynamic." */
+ /* dg-message "originally specified here" "" { target *-*-* } 40 */
+@dynamic three; /* { dg-error "no declaration of property .three. found in the interface" } */
+@end
diff --git a/gcc/testsuite/obj-c++.dg/property/fsf-property-basic.mm b/gcc/testsuite/obj-c++.dg/property/fsf-property-basic.mm
index 502ac0d806e..e7f8cbb7730 100644
--- a/gcc/testsuite/obj-c++.dg/property/fsf-property-basic.mm
+++ b/gcc/testsuite/obj-c++.dg/property/fsf-property-basic.mm
@@ -1,26 +1,16 @@
/* Basic test, auto-generated getter/setter based on property name. */
/* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
#ifdef __cplusplus
extern "C" {
#endif
-extern int printf (const char *fmt,...) ;
+extern int printf (const char *fmt,...);
extern void abort (void);
-typedef struct objc_class *Class;
+#include <objc/objc.h>
+#include <objc/runtime.h>
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-
-#else
-
-extern id class_create_instance(Class);
-
-#endif
#ifdef __cplusplus
}
#endif
@@ -28,28 +18,25 @@ extern id class_create_instance(Class);
@interface Bar
{
@public
-#ifdef __NEXT_RUNTIME__
Class isa;
-#else
- Class class_pointer;
-#endif
- int var;
+ int FooBar;
}
+ (id) initialize;
+ (id) alloc ;
- - (id) init;
-
+- (id) init;
+- (int) whatIsFooBar;
@property int FooBar;
@end
@implementation Bar
+initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance (self, 0); }
- (id) init {return self;}
-@property int FooBar ;
+- (int) whatIsFooBar { return self->FooBar; }
+@synthesize FooBar;
@end
int main(int argc, char *argv[]) {
@@ -60,21 +47,23 @@ int main(int argc, char *argv[]) {
and operate correctly. */
[f setFooBar:1];
- if (f->_FooBar != 1)
- { printf ("setFooBar did not set _FooBar\n"); abort ();}
+ if ([f whatIsFooBar] != 1)
+ { printf ("setFooBar did not set FooBar\n"); abort ();}
res = [f FooBar];
if (res != 1 )
{ printf ("[f FooBar] = %d\n", res); abort ();}
- /* Now check the short-cut CLASS.property syntax. */
+ /* Now check the short-cut object.property syntax. */
+ /* Read... */
res = f.FooBar;
if (res != 1 )
- { printf ("f,FooBar = %d\n", res); abort ();}
-
+ { printf ("f.FooBar = %d\n", res); abort ();}
+
+ /* .... write. */
f.FooBar = 0;
- printf ("seems OK\n", res);
+ /* printf ("seems OK\n", res); */
return f.FooBar;
}
diff --git a/gcc/testsuite/obj-c++.dg/property/fsf-property-method-access.mm b/gcc/testsuite/obj-c++.dg/property/fsf-property-method-access.mm
index 4052d1600d3..8053c84f9f7 100644
--- a/gcc/testsuite/obj-c++.dg/property/fsf-property-method-access.mm
+++ b/gcc/testsuite/obj-c++.dg/property/fsf-property-method-access.mm
@@ -1,25 +1,16 @@
/* test access in methods, auto-generated getter/setter based on property name. */
/* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
#ifdef __cplusplus
extern "C" {
#endif
-extern int printf (const char *fmt,...) ;
-extern void abort (void);
-
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-#else
+extern int printf (const char *fmt,...);
+extern void abort (void);
-extern id class_create_instance(Class);
+#include <objc/objc.h>
+#include <objc/runtime.h>
-#endif
#ifdef __cplusplus
}
#endif
@@ -27,11 +18,8 @@ extern id class_create_instance(Class);
@interface Bar
{
@public
-#ifdef __NEXT_RUNTIME__
Class isa;
-#else
- Class class_pointer;
-#endif
+ int FooBar;
}
+ (id) initialize;
+ (id) alloc ;
@@ -46,11 +34,11 @@ extern id class_create_instance(Class);
@implementation Bar
+initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance(self, 0);}
- (id) init {return self;}
-@property int FooBar;
+@synthesize FooBar;
- (int) lookAtProperty { return FooBar; }
- (void) setProperty: (int) v { FooBar = v; }
@@ -65,8 +53,8 @@ int main(int argc, char *argv[]) {
and operate correctly. */
[f setProperty:11];
- if (f->_FooBar != 11)
- { printf ("setProperty did not set _FooBar\n"); abort ();}
+ if (f.FooBar != 11)
+ { printf ("setProperty did not set FooBar\n"); abort ();}
res = [f lookAtProperty];
if (res != 11 )
diff --git a/gcc/testsuite/obj-c++.dg/property/fsf-property-named-ivar.mm b/gcc/testsuite/obj-c++.dg/property/fsf-property-named-ivar.mm
index 4b29c92c7b1..8538a1f5601 100644
--- a/gcc/testsuite/obj-c++.dg/property/fsf-property-named-ivar.mm
+++ b/gcc/testsuite/obj-c++.dg/property/fsf-property-named-ivar.mm
@@ -1,25 +1,16 @@
/* Basic test, auto-generated getter/setter based on named ivar */
/* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
#ifdef __cplusplus
extern "C" {
#endif
-extern int printf (const char *fmt,...) ;
-extern void abort (void);
-
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-#else
+extern int printf (const char *fmt,...);
+extern void abort (void);
-extern id class_create_instance(Class);
+#include <objc/objc.h>
+#include <objc/runtime.h>
-#endif
#ifdef __cplusplus
}
#endif
@@ -27,11 +18,7 @@ extern id class_create_instance(Class);
@interface Bar
{
@public
-#ifdef __NEXT_RUNTIME__
Class isa;
-#else
- Class class_pointer;
-#endif
int var;
}
+ (id) initialize;
@@ -44,11 +31,11 @@ extern id class_create_instance(Class);
@implementation Bar
+initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance (self, 0); }
- (id) init {return self;}
-@property (ivar = var) int FooBar ;
+@synthesize FooBar = var;
@end
int main(int argc, char *argv[]) {
@@ -67,7 +54,7 @@ int main(int argc, char *argv[]) {
if (res != 1234 )
{ printf ("[f FooBar] = %d\n", res); abort ();}
- /* Now check the short-cut CLASS.property syntax. */
+ /* Now check the short-cut object.property syntax. */
/* Read .... */
res = f.FooBar;
if (res != 1234 )
diff --git a/gcc/testsuite/obj-c++.dg/property/property-1.mm b/gcc/testsuite/obj-c++.dg/property/property-1.mm
index c9b9c46423a..b89d34bf2a4 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-1.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-1.mm
@@ -1,6 +1,5 @@
/* This program tests use of property provided setter/getter functions. */
/* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-additional-sources "../../objc-obj-c++-shared/Object1.mm" } */
#import "../../objc-obj-c++-shared/Object1.h"
@@ -9,11 +8,11 @@
{
int iVar;
}
-@property int FooBar;
+@property (setter=MySetter:) int FooBar;
@end
@implementation Bar
-@property (ivar = iVar, setter = MySetter:) int FooBar;
+@synthesize FooBar=iVar;
- (void) MySetter : (int) value { iVar = value; }
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-1.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-1.mm
index 2989c3b9295..cae1a56154d 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-1.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-1.mm
@@ -1,14 +1,13 @@
-/* This program checks for proper use of 'readonly' attribute. */
/* { dg-do compile } */
@interface Bar
{
int iVar;
}
-@property (readonly) int FooBar;
+@property int fooBar;
@end
@implementation Bar
-@property int FooBar; /* { dg-error " property 'FooBar' 'readonly' attribute conflicts with its interface version" } */
-
-@end
+@end /* { dg-warning "incomplete implementation of class .Bar." } */
+ /* { dg-warning "method definition for .-setFooBar:. not found" "" { target *-*-* } 11 } */
+ /* { dg-warning "method definition for .-fooBar. not found" "" { target *-*-* } 11 } */
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-2.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-2.mm
index 7046da84732..f730fe84644 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-2.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-2.mm
@@ -1,9 +1,8 @@
-/* This program checks for proper declaration of property. */
/* { dg-do compile } */
@interface Bar
@end
@implementation Bar
-@property int foo; /* { dg-error "no declaration of property 'foo' found in the interface" } */
+@property int FooBar; /* { dg-error "property declaration not in @interface or @protocol context" } */
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-3.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-3.mm
index 07438a6f375..a749c28c69c 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-3.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-3.mm
@@ -1,14 +1,16 @@
-/* Property name cannot match the ivar name. */
/* { dg-do compile } */
-/* Suppress warnings for incomplete class definition etc. */
-/* { dg-options "-w" } */
@interface Person
{
char *firstName;
}
-@property char *firstName; /* { dg-error "property 'firstName' may not have the same name as an ivar in the class" } */
+@property char *firstName;
@end
@implementation Person
-@end
+@dynamic firstName;
+/* FIXME - there is a problem with the testuite in running the following test. The compiler
+ generates the messages, but the testsuite still complains. */
+/*@synthesize firstName;*/ /* dg-error "property .firstName. already specified in .@dynamic." */
+ /* dg-message "originally specified here" "" { target *-*-* } 11 */
+@end
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-4.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-4.mm
index b3dbb605278..cc25d84af9b 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-4.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-4.mm
@@ -1,18 +1,17 @@
-/* Property cannot be accessed in class method. */
/* { dg-do compile } */
@interface Person
{
+ char *fullName;
}
@property char *fullName;
+ (void) testClass;
@end
+
@implementation Person
-@property char *fullName;
+@synthesize fullName;
+ (void) testClass {
- fullName = "MyName"; /* { dg-error "property 'fullName' accessed in class method" } */
- /* { dg-error "'fullName' was not declared in this scope" "" { target *-*-* } 14 } */
+ self.fullName = "MyName"; /* { dg-error "request for member .fullName." } */
}
@end
-
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm
index 7a9090ad056..403f6841c8d 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm
@@ -1,7 +1,5 @@
-/* getter/setter cannot be specified in an interface. */
/* { dg-do compile } */
@interface Foo
@property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
-@end /* { dg-warning "getter = \\'HELLO\\' may not be specified in an interface" } */
- /* { dg-warning "setter = \\'THERE\\:\\' may not be specified in an interface" "" { target *-*-* } 6 } */
+@end
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-7.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-7.mm
index 506f097eb2a..4c3d5d7d366 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-7.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-7.mm
@@ -1,13 +1,14 @@
-/* Cannot write into a read-only property. */
/* { dg-do compile } */
-/* Suppress warnings for incomplete class definition etc. */
-/* { dg-options "-w" } */
@interface NSArray
+{
+ int count;
+}
@property(readonly) int count;
@end
@implementation NSArray
+@synthesize count;
@end
void foo (NSArray *ans[], id pid, id apid[], int i) {
diff --git a/gcc/testsuite/obj-c++.dg/property/synthesize-1.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-1.mm
index fb9b38ea1d8..3513c016e72 100644
--- a/gcc/testsuite/obj-c++.dg/property/synthesize-1.mm
+++ b/gcc/testsuite/obj-c++.dg/property/synthesize-1.mm
@@ -19,13 +19,35 @@
int v2;
int v3;
int v4;
+ int v5;
+ int v6;
+ int v7;
+ int v8;
}
+@property int v1;
+@property int v2;
+@property int v3;
+@property int v4;
+@property int v5;
+@property int v6;
+@property int v7;
+@property int v8;
@end
@implementation Test
@synthesize; /* { dg-error "expected identifier" } */
@synthesize v1, ; /* { dg-error "expected identifier" } */
-@synthesize v1, v2 = ; /* { dg-error "expected identifier" } */
-@synthesize v1, v2=v2, v3 = v3,v4; /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
-@synthesize v4; /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
+@synthesize v2, v3 = ; /* { dg-error "expected identifier" } */
+@synthesize v4, v5=v6, v6 = v5,v7;
+@synthesize v8;
+/* Some of the @synthesize above will fail due to syntax errors. The
+ compiler will then complain that the methods implementing the
+ properties are missing. That is correct, but we are not
+ interested. The following ones shut up the compiler. */
+- (int) v1 { return v1; }
+- (void) setV1: (int)a { v1 = a; }
+- (int) v2 { return v2; }
+- (void) setV2: (int)a { v2 = a; }
+- (int) v3 { return v3; }
+- (void) setV3: (int)a { v3 = a; }
@end
diff --git a/gcc/testsuite/obj-c++.dg/property/synthesize-2.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-2.mm
new file mode 100644
index 00000000000..dfa3fd576a5
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/property/synthesize-2.mm
@@ -0,0 +1,51 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+ Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@end
+
+@interface Test : MyRootClass
+{
+ int v1;
+}
+@property int v1;
+/* TODO: Test more types of properties with different semantics
+ (retain, copy, atomic, nonatomic, and test various C and
+ Objective-C types). */
+@end
+
+@implementation Test
+@synthesize v1;
+@end
+
+int main ()
+{
+ Test *object = [[Test alloc] init];
+
+ /* Check that the synthesized methods exist and work. Do not invoke
+ them via property syntax - that is another test. Here we just
+ want to test the synthesis of the methods. */
+ [object setV1: 400];
+
+ if ([object v1] != 400)
+ abort ();
+
+ return (0);
+}
+
diff --git a/gcc/testsuite/objc.dg/property/at-property-10.m b/gcc/testsuite/objc.dg/property/at-property-10.m
new file mode 100644
index 00000000000..bc6380cd5a6
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-10.m
@@ -0,0 +1,100 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax in a number of expressions. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int
+test (int g)
+{
+ return g;
+}
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+ MyRootClass *object2 = [[MyRootClass alloc] init];
+
+ object.a = 14;
+ object.a = object.a + object.a;
+
+ if (object.a != 28)
+ abort ();
+
+ object.a = 99;
+ /* TODO: The following one does not work yet. */
+ /* object.a++; */
+ object.a = object.a + 1;
+
+ if (object.a != 100)
+ abort ();
+
+ object.a = 99;
+ object.a *= 2;
+
+ if (object.a != 198)
+ abort ();
+
+ {
+ int f = object.a;
+
+ if (f != 198)
+ abort ();
+
+ if (f != object.a)
+ abort ();
+
+ if (object.a != f)
+ abort ();
+
+ object.a = object.a;
+
+ if (object.a != 198)
+ abort ();
+ }
+
+ if (test (object.a) != 198)
+ abort ();
+
+ object.a = -object.a;
+
+ if (object.a != -198)
+ abort ();
+
+ /* TODO: The following one does not work yet. */
+ /* for (object.a = 0; object.a < 99; object.a++) */
+ for (object.a = 0; object.a < 99; object.a = object.a + 1)
+ object2.a = object.a;
+
+ if (object2.a != object.a - 1)
+ abort ();
+
+ if (object2.a != 98)
+ abort ();
+
+ if (object.a != 99)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-11.m b/gcc/testsuite/objc.dg/property/at-property-11.m
new file mode 100644
index 00000000000..84857e0659a
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-11.m
@@ -0,0 +1,43 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test that properties are found even if implemented in superclasses. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+@interface MySubClass : MyRootClass
+@end
+
+@implementation MySubClass
+@end
+
+int main (void)
+{
+ MySubClass *object = [[MySubClass alloc] init];
+
+ object.a = 40;
+ if (object.a != 40)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-2.m b/gcc/testsuite/objc.dg/property/at-property-2.m
index 23bd4850310..19d59fdaa6e 100644
--- a/gcc/testsuite/objc.dg/property/at-property-2.m
+++ b/gcc/testsuite/objc.dg/property/at-property-2.m
@@ -6,8 +6,8 @@
{
Class isa;
}
-@property id name __attribute__((deprecated));
-@property id table __attribute__((xxx)); /* { dg-warning ".xxx. attribute directive ignored" } */
+@property int name __attribute__((deprecated));
+@property int table __attribute__((xxx)); /* { dg-warning ".xxx. attribute directive ignored" } */
@property void function (void); /* { dg-error "declared as a function" } */
@property typedef int j; /* { dg-error "expected" } */
@end
diff --git a/gcc/testsuite/objc.dg/property/at-property-4.m b/gcc/testsuite/objc.dg/property/at-property-4.m
index 05223a3fa22..e327930f87b 100644
--- a/gcc/testsuite/objc.dg/property/at-property-4.m
+++ b/gcc/testsuite/objc.dg/property/at-property-4.m
@@ -6,36 +6,35 @@
{
Class isa;
}
-- (id) myGetter;
-- (id) myGetterB;
-- (void) mySetter: (id)property;
-- (void) mySetterB: (id)property;
+- (int) myGetter;
+- (int) myGetterB;
+- (int) myGetter2;
+- (void) mySetter: (int)property;
+- (void) mySetterB: (int)property;
+- (void) mySetter2: (int)property;
/* Test that all the new property attributes can be parsed. */
@property (assign) id property_a;
@property (copy) id property_b;
-@property (nonatomic) id property_c;
-@property (readonly) id property_d;
-@property (readwrite) id property_e;
+@property (nonatomic) int property_c;
+@property (readonly) int property_d;
+@property (readwrite) int property_e;
@property (retain) id property_f;
-@property (release) id property_g; /* { dg-error "unknown property attribute" } */
+@property (release) int property_g; /* { dg-error "unknown property attribute" } */
-/* The following will be enabled when @synthesized is implemented. */
-/* @property (getter=myGetter) id property_h; */
-/* @property (setter=mySetter:) id property_i; */
+@property (getter=myGetter) int property_h;
+@property (setter=mySetter:) int property_i;
/* Now test various problems. */
@property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */
-/* The following will be enabled when @synthesized is implemented. */
-/* @property (readonly, setter=setA:) int b; */ /* dg-warning ".readonly. attribute conflicts with .setter. attribute" */
+@property (readonly, setter=mySetterB:) int b; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
@property (assign, retain) id c; /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */
@property (assign, copy) id d; /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */
@property (copy, retain) id e; /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */
-/* The following will be enabled when @synthesized is implemented. */
-/* @property (setter=mySetter:,setter=mySetterB:) id f; */ /* dg-error ".setter. attribute may only be specified once" */
-/* @property (getter=myGetter:,getter=myGetterB:) id f; */ /* dg-error ".getter. attribute may only be specified once" */
+@property (setter=mySetter:,setter=mySetter2:) int f; /* { dg-error ".setter. attribute may only be specified once" } */
+@property (getter=myGetter, getter=myGetter2 ) int g; /* { dg-error ".getter. attribute may only be specified once" } */
@end
diff --git a/gcc/testsuite/objc.dg/property/at-property-5.m b/gcc/testsuite/objc.dg/property/at-property-5.m
new file mode 100644
index 00000000000..e4abd27c284
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-5.m
@@ -0,0 +1,34 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ id property_a;
+ int property_b;
+ int property_c;
+ int property_d;
+ id property_e;
+ id property_f;
+ id property_g;
+ id property_h;
+}
+
+/* Test various error messages. */
+@property id property_a; /* { dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" } */
+ /* { dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 20 } */
+@property int property_b = 4; /* { dg-error "expected" } */
+@property (retain) int property_c; /* { dg-error ".retain. attribute is only valid for Objective-C objects" } */
+@property (copy) int property_d; /* { dg-error ".copy. attribute is only valid for Objective-C objects" } */
+
+@property (retain) id property_e;
+@property (retain) id property_f;
+@property (retain) id property_g;
+@property (retain) id property_h;
+@property (retain) id property_e; /* { dg-error "redeclaration of property .property_e." } */
+ /* { dg-message "originally declared here" "" { target *-*-* } 26 } */
+@end
+
+@property id test; /* { dg-error "property declaration not in .interface or .protocol context" } */
diff --git a/gcc/testsuite/objc.dg/property/at-property-6.m b/gcc/testsuite/objc.dg/property/at-property-6.m
new file mode 100644
index 00000000000..a97c0b05f67
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-6.m
@@ -0,0 +1,60 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+ and with standard names. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) a
+{
+ return a;
+}
+- (void) setA: (int)value
+{
+ a = value;
+}
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ if (object.a != 0)
+ abort ();
+
+ object.a = 14;
+
+ if (object.a != 14)
+ abort ();
+
+ object.a = 23;
+
+ if (object.a != 23)
+ abort ();
+
+ object.a = 78;
+
+ if (object.a != 78)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-7.m b/gcc/testsuite/objc.dg/property/at-property-7.m
new file mode 100644
index 00000000000..dce27640781
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-7.m
@@ -0,0 +1,57 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+ and with a non-standard name for the getter. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property (getter = getA) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) getA
+{
+ return a;
+}
+- (void) setA: (int)value
+{
+ a = value;
+}
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ object.a = 14;
+
+ if (object.a != 14)
+ abort ();
+
+ object.a = 23;
+
+ if (object.a != 23)
+ abort ();
+
+ object.a = 78;
+
+ if (object.a != 78)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-8.m b/gcc/testsuite/objc.dg/property/at-property-8.m
new file mode 100644
index 00000000000..eb158893724
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-8.m
@@ -0,0 +1,57 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax with non-synthesized setter/getter
+ and with a non-standard name for the setter. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property (setter = writeA:) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+
+- (int) a
+{
+ return a;
+}
+- (void) writeA: (int)value
+{
+ a = value;
+}
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ object.a = 14;
+
+ if (object.a != 14)
+ abort ();
+
+ object.a = 23;
+
+ if (object.a != 23)
+ abort ();
+
+ object.a = 78;
+
+ if (object.a != 78)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/at-property-9.m b/gcc/testsuite/objc.dg/property/at-property-9.m
new file mode 100644
index 00000000000..203eb3003fd
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/at-property-9.m
@@ -0,0 +1,49 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+/* Test the property syntax with synthesized setter/getter
+ and with a non-standard name for the getter and setter. */
+
+#include <stdlib.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+
+@interface MyRootClass
+{
+ Class isa;
+ int a;
+}
+@property (getter = giveMeA, setter = writeA:) int a;
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@synthesize a;
+@end
+
+int main (void)
+{
+ MyRootClass *object = [[MyRootClass alloc] init];
+
+ object.a = 14;
+
+ if (object.a != 14)
+ abort ();
+
+ object.a = 23;
+
+ if (object.a != 23)
+ abort ();
+
+ object.a = 78;
+
+ if (object.a != 78)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/property/dynamic-1.m b/gcc/testsuite/objc.dg/property/dynamic-1.m
index b91a030a89d..8f9737139dc 100644
--- a/gcc/testsuite/objc.dg/property/dynamic-1.m
+++ b/gcc/testsuite/objc.dg/property/dynamic-1.m
@@ -20,11 +20,15 @@
int v3;
int v4;
}
+@property int v1;
+@property int v2;
+@property int v3;
+@property int v4;
@end
@implementation Test
@dynamic; /* { dg-error "expected identifier" } */
@dynamic v1, ; /* { dg-error "expected identifier" } */
-@dynamic v1, v2, v3; /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
-@dynamic v4; /* { dg-error ".@dynamic. is not supported in this version of the compiler" } */
+@dynamic v1, v2, v3;
+@dynamic v4;
@end
diff --git a/gcc/testsuite/objc.dg/property/dynamic-2.m b/gcc/testsuite/objc.dg/property/dynamic-2.m
new file mode 100644
index 00000000000..313d8dc8222
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/dynamic-2.m
@@ -0,0 +1,44 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+@interface MyRootClass
+{
+ Class isa;
+}
+@end
+
+@implementation MyRootClass
+@end
+
+@dynamic isa; /* { dg-error ".@dynamic. not in @implementation context" } */
+
+@interface Test : MyRootClass
+{
+ int v1;
+}
+@end
+@implementation Test
+@end
+
+
+@interface Test (Category)
+@end
+@implementation Test (Category)
+@dynamic v1; /* { dg-error ".@dynamic. can not be used in categories" } */
+@end
+
+
+@interface AnotherTest : MyRootClass
+{
+}
+@property int one;
+@end
+
+@implementation AnotherTest
+@dynamic one;
+@dynamic one; /* { dg-error "property .one. already specified in .@dynamic." } */
+ /* { dg-message "originally specified here" "" { target *-*-* } 40 } */
+@dynamic three; /* { dg-error "no declaration of property .three. found in the interface" } */
+@end
diff --git a/gcc/testsuite/objc.dg/property/fsf-property-basic.m b/gcc/testsuite/objc.dg/property/fsf-property-basic.m
index 13a00a2b381..20fd9788477 100644
--- a/gcc/testsuite/objc.dg/property/fsf-property-basic.m
+++ b/gcc/testsuite/objc.dg/property/fsf-property-basic.m
@@ -1,47 +1,34 @@
/* Basic test, auto-generated getter/setter based on property name. */
/* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
extern int printf (char *fmt,...) ;
extern void abort (void);
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-
-#else
-
-extern id class_create_instance(Class);
-
-#endif
+#include <objc/objc.h>
+#include <objc/runtime.h>
@interface Bar
{
@public
-#ifdef __NEXT_RUNTIME__
Class isa;
-#else
- Class class_pointer;
-#endif
+ int FooBar;
}
+ (id) initialize;
+ (id) alloc ;
- (id) init;
-
+- (int) whatIsFooBar;
@property int FooBar;
@end
@implementation Bar
+initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance (self, 0); }
- (id) init {return self;}
-@property int FooBar ;
+- (int) whatIsFooBar { return self->FooBar; }
+@synthesize FooBar;
@end
int main(int argc, char *argv[]) {
@@ -52,15 +39,15 @@ int main(int argc, char *argv[]) {
and operate correctly. */
[f setFooBar:1];
- if (f->_FooBar != 1)
- { printf ("setFooBar did not set _FooBar\n"); abort ();}
+ if ([f whatIsFooBar] != 1)
+ { printf ("setFooBar did not set FooBar\n"); abort ();}
res = [f FooBar];
if (res != 1 )
{ printf ("[f FooBar] = %d\n", res); abort ();}
- /* Now check the short-cut CLASS.property syntax. */
+ /* Now check the short-cut object.property syntax. */
/* Read... */
res = f.FooBar;
if (res != 1 )
diff --git a/gcc/testsuite/objc.dg/property/fsf-property-method-access.m b/gcc/testsuite/objc.dg/property/fsf-property-method-access.m
index fae49690c73..866f52208a1 100644
--- a/gcc/testsuite/objc.dg/property/fsf-property-method-access.m
+++ b/gcc/testsuite/objc.dg/property/fsf-property-method-access.m
@@ -1,31 +1,17 @@
/* test access in methods, auto-generated getter/setter based on property name. */
/* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
extern int printf (char *fmt,...) ;
extern void abort (void);
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-
-#else
-
-extern id class_create_instance(Class);
-
-#endif
+#include <objc/objc.h>
+#include <objc/runtime.h>
@interface Bar
{
@public
-#ifdef __NEXT_RUNTIME__
Class isa;
-#else
- Class class_pointer;
-#endif
+ int FooBar;
}
+ (id) initialize;
+ (id) alloc ;
@@ -40,11 +26,11 @@ extern id class_create_instance(Class);
@implementation Bar
+initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance(self, 0);}
- (id) init {return self;}
-@property int FooBar;
+@synthesize FooBar;
- (int) lookAtProperty { return FooBar; }
- (void) setProperty: (int) v { FooBar = v; }
@@ -59,8 +45,8 @@ int main(int argc, char *argv[]) {
and operate correctly. */
[f setProperty:11];
- if (f->_FooBar != 11)
- { printf ("setProperty did not set _FooBar\n"); abort ();}
+ if (f.FooBar != 11)
+ { printf ("setProperty did not set FooBar\n"); abort ();}
res = [f lookAtProperty];
if (res != 11 )
diff --git a/gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m b/gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m
index 837d303f317..3e0b52976b0 100644
--- a/gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m
+++ b/gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m
@@ -1,31 +1,16 @@
/* Basic test, auto-generated getter/setter based on named ivar */
/* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
extern int printf (char *fmt,...) ;
extern void abort (void);
-typedef struct objc_class *Class;
-
-#ifdef __NEXT_RUNTIME__
-
-extern id class_createInstance(Class, long);
-#define class_create_instance(C) class_createInstance(C, 0)
-
-#else
-
-extern id class_create_instance(Class);
-
-#endif
+#include <objc/objc.h>
+#include <objc/runtime.h>
@interface Bar
{
@public
-#ifdef __NEXT_RUNTIME__
Class isa;
-#else
- Class class_pointer;
-#endif
int var;
}
+ (id) initialize;
@@ -38,11 +23,11 @@ extern id class_create_instance(Class);
@implementation Bar
+initialize { return self;}
-+ (id) alloc { return class_create_instance(self);}
++ (id) alloc { return class_createInstance (self, 0); }
- (id) init {return self;}
-@property (ivar = var) int FooBar ;
+@synthesize FooBar = var;
@end
int main(int argc, char *argv[]) {
@@ -61,7 +46,7 @@ int main(int argc, char *argv[]) {
if (res != 1234 )
{ printf ("[f FooBar] = %d\n", res); abort ();}
- /* Now check the short-cut CLASS.property syntax. */
+ /* Now check the short-cut object.property syntax. */
/* Read .... */
res = f.FooBar;
if (res != 1234 )
diff --git a/gcc/testsuite/objc.dg/property/property-1.m b/gcc/testsuite/objc.dg/property/property-1.m
index 89537ca925c..fbc181eb75b 100644
--- a/gcc/testsuite/objc.dg/property/property-1.m
+++ b/gcc/testsuite/objc.dg/property/property-1.m
@@ -1,7 +1,6 @@
/* This program tests use of property provided setter/getter functions. */
/* { dg-options "-std=c99" } */
/* { dg-do run } */
-/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-additional-sources "../../objc-obj-c++-shared/Object1.m" } */
#import "../../objc-obj-c++-shared/Object1.h"
@@ -10,11 +9,11 @@
{
int iVar;
}
-@property int FooBar;
+@property (setter=MySetter:) int FooBar;
@end
@implementation Bar
-@property (ivar = iVar, setter = MySetter:) int FooBar;
+@synthesize FooBar=iVar;
- (void) MySetter : (int) value { iVar = value; }
diff --git a/gcc/testsuite/objc.dg/property/property-2.m b/gcc/testsuite/objc.dg/property/property-2.m
index 2a923e060ef..c14d759d3e8 100644
--- a/gcc/testsuite/objc.dg/property/property-2.m
+++ b/gcc/testsuite/objc.dg/property/property-2.m
@@ -7,6 +7,8 @@
/* Force ABI = 0 in the NeXT headers, also suppress deprecation warnings. */
/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations" } */
+/* FIXME: There is no reason to use NSString in this file. */
+
#include <objc/objc-api.h>
#include <Foundation/Foundation.h>
diff --git a/gcc/testsuite/objc.dg/property/property-neg-1.m b/gcc/testsuite/objc.dg/property/property-neg-1.m
index ffb825363e1..cae1a56154d 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-1.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-1.m
@@ -1,14 +1,13 @@
-/* This program checks for proper use of 'readonly' attribute. */
/* { dg-do compile } */
@interface Bar
{
int iVar;
}
-@property (readonly) int FooBar;
+@property int fooBar;
@end
@implementation Bar
-@property int FooBar; /* { dg-error "property 'FooBar' 'readonly' attribute conflicts with its interface version" } */
-
-@end
+@end /* { dg-warning "incomplete implementation of class .Bar." } */
+ /* { dg-warning "method definition for .-setFooBar:. not found" "" { target *-*-* } 11 } */
+ /* { dg-warning "method definition for .-fooBar. not found" "" { target *-*-* } 11 } */
diff --git a/gcc/testsuite/objc.dg/property/property-neg-2.m b/gcc/testsuite/objc.dg/property/property-neg-2.m
index 7046da84732..f730fe84644 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-2.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-2.m
@@ -1,9 +1,8 @@
-/* This program checks for proper declaration of property. */
/* { dg-do compile } */
@interface Bar
@end
@implementation Bar
-@property int foo; /* { dg-error "no declaration of property 'foo' found in the interface" } */
+@property int FooBar; /* { dg-error "property declaration not in @interface or @protocol context" } */
@end
diff --git a/gcc/testsuite/objc.dg/property/property-neg-3.m b/gcc/testsuite/objc.dg/property/property-neg-3.m
index 5b4804433f1..0b30931a881 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-3.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-3.m
@@ -1,14 +1,14 @@
-/* Property name cannot match the ivar name. */
/* { dg-do compile } */
-/* Suppress warnings for incomplete class definition etc. */
-/* { dg-options "-w" } */
@interface Person
{
char *firstName;
}
-@property char *firstName; /* { dg-error "property 'firstName' may not have the same name as an ivar in the class" } */
+@property char *firstName;
@end
@implementation Person
+@dynamic firstName;
+@synthesize firstName; /* { dg-error "property .firstName. already specified in .@dynamic." } */
+ /* { dg-message "originally specified here" "" { target *-*-* } 11 } */
@end
diff --git a/gcc/testsuite/objc.dg/property/property-neg-4.m b/gcc/testsuite/objc.dg/property/property-neg-4.m
index 960c6d63372..cc25d84af9b 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-4.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-4.m
@@ -1,17 +1,17 @@
-/* Property cannot be accessed in class method. */
/* { dg-do compile } */
@interface Person
{
+ char *fullName;
}
@property char *fullName;
+ (void) testClass;
@end
+
@implementation Person
-@property char *fullName;
+@synthesize fullName;
+ (void) testClass {
- fullName = "MyName"; /* { dg-error "property 'fullName' accessed in class method" } */
+ self.fullName = "MyName"; /* { dg-error "request for member .fullName." } */
}
@end
-
diff --git a/gcc/testsuite/objc.dg/property/property-neg-5.m b/gcc/testsuite/objc.dg/property/property-neg-5.m
index 7a9090ad056..403f6841c8d 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-5.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-5.m
@@ -1,7 +1,5 @@
-/* getter/setter cannot be specified in an interface. */
/* { dg-do compile } */
@interface Foo
@property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */
-@end /* { dg-warning "getter = \\'HELLO\\' may not be specified in an interface" } */
- /* { dg-warning "setter = \\'THERE\\:\\' may not be specified in an interface" "" { target *-*-* } 6 } */
+@end
diff --git a/gcc/testsuite/objc.dg/property/property-neg-7.m b/gcc/testsuite/objc.dg/property/property-neg-7.m
index 506f097eb2a..4c3d5d7d366 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-7.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-7.m
@@ -1,13 +1,14 @@
-/* Cannot write into a read-only property. */
/* { dg-do compile } */
-/* Suppress warnings for incomplete class definition etc. */
-/* { dg-options "-w" } */
@interface NSArray
+{
+ int count;
+}
@property(readonly) int count;
@end
@implementation NSArray
+@synthesize count;
@end
void foo (NSArray *ans[], id pid, id apid[], int i) {
diff --git a/gcc/testsuite/objc.dg/property/synthesize-1.m b/gcc/testsuite/objc.dg/property/synthesize-1.m
index 09085d82e74..fbc8e03eebf 100644
--- a/gcc/testsuite/objc.dg/property/synthesize-1.m
+++ b/gcc/testsuite/objc.dg/property/synthesize-1.m
@@ -19,13 +19,35 @@
int v2;
int v3;
int v4;
+ int v5;
+ int v6;
+ int v7;
+ int v8;
}
+@property int v1;
+@property int v2;
+@property int v3;
+@property int v4;
+@property int v5;
+@property int v6;
+@property int v7;
+@property int v8;
@end
@implementation Test
@synthesize; /* { dg-error "expected identifier" } */
@synthesize v1, ; /* { dg-error "expected identifier" } */
-@synthesize v1, v2 = ; /* { dg-error "expected identifier" } */
-@synthesize v1, v2=v2, v3 = v3,v4; /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
-@synthesize v4; /* { dg-error ".@synthesize. is not supported in this version of the compiler" } */
+@synthesize v2, v3 = ; /* { dg-error "expected identifier" } */
+@synthesize v4, v5=v6, v6 = v5,v7;
+@synthesize v8;
+/* Some of the @synthesize above will fail due to syntax errors. The
+ compiler will then complain that the methods implementing the
+ properties are missing. That is correct, but we are not
+ interested. The following ones shut up the compiler. */
+- (int) v1 { return v1; }
+- (void) setV1: (int)a { v1 = a; }
+- (int) v2 { return v2; }
+- (void) setV2: (int)a { v2 = a; }
+- (int) v3 { return v3; }
+- (void) setV3: (int)a { v3 = a; }
@end
diff --git a/gcc/testsuite/objc.dg/property/synthesize-2.m b/gcc/testsuite/objc.dg/property/synthesize-2.m
new file mode 100644
index 00000000000..4bc3e3c7729
--- /dev/null
+++ b/gcc/testsuite/objc.dg/property/synthesize-2.m
@@ -0,0 +1,50 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010. */
+/* { dg-do run } */
+
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+@interface MyRootClass
+{
+ Class isa;
+}
++ (id) initialize;
++ (id) alloc;
+- (id) init;
+@end
+
+@implementation MyRootClass
++ (id) initialize { return self; }
++ (id) alloc { return class_createInstance (self, 0); }
+- (id) init { return self; }
+@end
+
+@interface Test : MyRootClass
+{
+ int v1;
+}
+@property int v1;
+/* TODO: Test more types of properties with different semantics
+ (retain, copy, atomic, nonatomic, and test various C and
+ Objective-C types). */
+@end
+
+@implementation Test
+@synthesize v1;
+@end
+
+int main (void)
+{
+ Test *object = [[Test alloc] init];
+
+ /* Check that the synthesized methods exist and work. Do not invoke
+ them via property syntax - that is another test. Here we just
+ want to test the synthesis of the methods. */
+ [object setV1: 400];
+
+ if ([object v1] != 400)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/torture/tls/thr-init-2.m b/gcc/testsuite/objc.dg/torture/tls/thr-init-2.m
index 04231a82110..cdbef4d77bc 100644
--- a/gcc/testsuite/objc.dg/torture/tls/thr-init-2.m
+++ b/gcc/testsuite/objc.dg/torture/tls/thr-init-2.m
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-require-effective-target tls }
+// { dg-require-effective-target tls_runtime }
// { dg-add-options tls }
extern void _exit(int);
diff --git a/gcc/testsuite/objc.dg/torture/tls/thr-init-3.m b/gcc/testsuite/objc.dg/torture/tls/thr-init-3.m
index 9f354b34185..b52c87391ea 100644
--- a/gcc/testsuite/objc.dg/torture/tls/thr-init-3.m
+++ b/gcc/testsuite/objc.dg/torture/tls/thr-init-3.m
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-require-effective-target tls } */
+/* { dg-require-effective-target tls_runtime } */
/* { dg-add-options tls } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-additional-sources "../../../objc-obj-c++-shared/Object1.m" } */
diff --git a/gcc/testsuite/objc.dg/torture/tls/thr-init.m b/gcc/testsuite/objc.dg/torture/tls/thr-init.m
index 663965180d2..986b425f744 100644
--- a/gcc/testsuite/objc.dg/torture/tls/thr-init.m
+++ b/gcc/testsuite/objc.dg/torture/tls/thr-init.m
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-require-effective-target tls } */
+/* { dg-require-effective-target tls_runtime } */
/* { dg-add-options tls } */
extern void _exit(int);
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 1894572000e..45902e5bafd 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -910,19 +910,7 @@ rewrite_reciprocal (gimple_stmt_iterator *bsi)
add_referenced_var (var);
DECL_GIMPLE_REG_P (var) = 1;
- /* For vectors, create a VECTOR_CST full of 1's. */
- if (TREE_CODE (type) == VECTOR_TYPE)
- {
- int i, len;
- tree list = NULL_TREE;
- real_one = build_real (TREE_TYPE (type), dconst1);
- len = TYPE_VECTOR_SUBPARTS (type);
- for (i = 0; i < len; i++)
- list = tree_cons (NULL, real_one, list);
- real_one = build_vector (type, list);
- }
- else
- real_one = build_real (type, dconst1);
+ real_one = build_one_cst (type);
stmt1 = gimple_build_assign_with_ops (RDIV_EXPR,
var, real_one, gimple_assign_rhs2 (stmt));
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 4b1bd443054..c213673e20b 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -2725,13 +2725,11 @@ get_initial_def_for_induction (gimple iv_phi)
expr, step_expr);
}
- t = NULL_TREE;
- for (i = 0; i < nunits; i++)
- t = tree_cons (NULL_TREE, unshare_expr (new_name), t);
+ t = unshare_expr (new_name);
gcc_assert (CONSTANT_CLASS_P (new_name));
stepvectype = get_vectype_for_scalar_type (TREE_TYPE (new_name));
gcc_assert (stepvectype);
- vec = build_vector (stepvectype, t);
+ vec = build_vector_from_val (stepvectype, t);
vec_step = vect_init_vector (iv_phi, vec, stepvectype, NULL);
@@ -2785,11 +2783,9 @@ get_initial_def_for_induction (gimple iv_phi)
expr = build_int_cst (TREE_TYPE (step_expr), nunits);
new_name = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
expr, step_expr);
- t = NULL_TREE;
- for (i = 0; i < nunits; i++)
- t = tree_cons (NULL_TREE, unshare_expr (new_name), t);
+ t = unshare_expr (new_name);
gcc_assert (CONSTANT_CLASS_P (new_name));
- vec = build_vector (stepvectype, t);
+ vec = build_vector_from_val (stepvectype, t);
vec_step = vect_init_vector (iv_phi, vec, stepvectype, NULL);
vec_def = induc_def;
@@ -3021,14 +3017,7 @@ get_initial_def_for_reduction (gimple stmt, tree init_val,
break;
}
- for (i = nunits - 1; i >= 0; --i)
- t = tree_cons (NULL_TREE, init_value, t);
-
- if (TREE_CONSTANT (init_val))
- init_def = build_vector (vectype, t);
- else
- init_def = build_constructor_from_list (vectype, t);
-
+ init_def = build_vector_from_val (vectype, init_value);
break;
default:
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 7a69db05ebb..fdaaff2865b 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -1986,12 +1986,7 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
if (neutral_op)
{
if (!neutral_vec)
- {
- t = NULL;
- for (i = 0; i < (unsigned) nunits; i++)
- t = tree_cons (NULL_TREE, neutral_op, t);
- neutral_vec = build_vector (vector_type, t);
- }
+ neutral_vec = build_vector_from_val (vector_type, neutral_op);
VEC_quick_push (tree, *vec_oprnds, neutral_vec);
}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 01fd5cfd14a..67e9e2bc445 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -987,9 +987,7 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
tree vec_inv;
tree vec_cst;
- tree t = NULL_TREE;
tree def;
- int i;
enum vect_def_type dt;
bool is_simple_use;
tree vector_type;
@@ -1033,11 +1031,7 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
- for (i = nunits - 1; i >= 0; --i)
- {
- t = tree_cons (NULL_TREE, op, t);
- }
- vec_cst = build_vector (vector_type, t);
+ vec_cst = build_vector_from_val (vector_type, op);
return vect_init_vector (stmt, vec_cst, vector_type, NULL);
}
@@ -1055,13 +1049,7 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "Create vector_inv.");
- for (i = nunits - 1; i >= 0; --i)
- {
- t = tree_cons (NULL_TREE, def, t);
- }
-
- /* FIXME: use build_constructor directly. */
- vec_inv = build_constructor_from_list (vector_type, t);
+ vec_inv = build_vector_from_val (vector_type, def);
return vect_init_vector (stmt, vec_inv, vector_type, NULL);
}
@@ -1320,7 +1308,8 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
tree fndecl, new_temp, def, rhs_type;
gimple def_stmt;
- enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
+ enum vect_def_type dt[3]
+ = {vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type};
gimple new_stmt = NULL;
int ncopies, j;
VEC(tree, heap) *vargs = NULL;
diff --git a/gcc/tree.c b/gcc/tree.c
index 48279ebc181..4de73ee4d2c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1366,6 +1366,29 @@ build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v)
return build_vector (type, nreverse (list));
}
+/* Build a vector of type VECTYPE where all the elements are SCs. */
+tree
+build_vector_from_val (tree vectype, tree sc)
+{
+ int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+ VEC(constructor_elt, gc) *v = NULL;
+
+ if (sc == error_mark_node)
+ return sc;
+
+ gcc_assert (lang_hooks.types_compatible_p (TREE_TYPE (sc),
+ TREE_TYPE (vectype)));
+
+ v = VEC_alloc (constructor_elt, gc, nunits);
+ for (i = 0; i < nunits; ++i)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
+
+ if (CONSTANT_CLASS_P (sc))
+ return build_vector_from_ctor (vectype, v);
+ else
+ return build_constructor (vectype, v);
+}
+
/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
are in the VEC pointed to by VALS. */
tree
@@ -1568,17 +1591,9 @@ build_one_cst (tree type)
case VECTOR_TYPE:
{
- tree scalar, cst;
- int i;
-
- scalar = build_one_cst (TREE_TYPE (type));
-
- /* Create 'vect_cst_ = {cst,cst,...,cst}' */
- cst = NULL_TREE;
- for (i = TYPE_VECTOR_SUBPARTS (type); --i >= 0; )
- cst = tree_cons (NULL_TREE, scalar, cst);
+ tree scalar = build_one_cst (TREE_TYPE (type));
- return build_vector (type, cst);
+ return build_vector_from_val (type, scalar);
}
case COMPLEX_TYPE:
diff --git a/gcc/tree.h b/gcc/tree.h
index b799aaa43a2..2de56c78735 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4038,6 +4038,7 @@ extern tree build_int_cst_type (tree, HOST_WIDE_INT);
extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
extern tree build_vector (tree, tree);
extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (tree, tree);
extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
extern tree build_constructor_single (tree, tree, tree);
extern tree build_constructor_from_list (tree, tree);
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 02a2b15032c..4eb9e2ffbdc 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,41 @@
+2010-10-28 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * src/arm/ffi.c (ffi_prep_args): Add VFP register argument handling
+ code, new parameter, and return value. Update comments.
+ (ffi_prep_cif_machdep): Add case for VFP struct return values. Add
+ call to layout_vfp_args().
+ (ffi_call_SYSV): Update declaration.
+ (ffi_call_VFP): New declaration.
+ (ffi_call): Add VFP struct return conditions. Call ffi_call_VFP()
+ when ABI is FFI_VFP.
+ (ffi_closure_VFP): New declaration.
+ (ffi_closure_SYSV_inner): Add new vfp_args parameter, update call to
+ ffi_prep_incoming_args_SYSV().
+ (ffi_prep_incoming_args_SYSV): Update parameters. Add VFP argument
+ case handling.
+ (ffi_prep_closure_loc): Pass ffi_closure_VFP to trampoline
+ construction under VFP hard-float.
+ (rec_vfp_type_p): New function.
+ (vfp_type_p): Same.
+ (place_vfp_arg): Same.
+ (layout_vfp_args): Same.
+ * src/arm/ffitarget.h (ffi_abi): Add FFI_VFP. Define FFI_DEFAULT_ABI
+ based on __ARM_PCS_VFP.
+ (FFI_EXTRA_CIF_FIELDS): Define for adding VFP hard-float specific
+ fields.
+ (FFI_TYPE_STRUCT_VFP_FLOAT): Define internally used type code.
+ (FFI_TYPE_STRUCT_VFP_DOUBLE): Same.
+ * src/arm/sysv.S (ffi_call_SYSV): Change call of ffi_prep_args() to
+ direct call. Move function pointer load upwards.
+ (ffi_call_VFP): New function.
+ (ffi_closure_VFP): Same.
+
+ * testsuite/lib/libffi-dg.exp (check-flags): New function.
+ (dg-skip-if): New function.
+ * testsuite/libffi.call/cls_double_va.c: Skip if target is arm*-*-*
+ and compiler options include -mfloat-abi=hard.
+ * testsuite/libffi.call/cls_longdouble_va.c: Same.
+
2010-10-01 Jakub Jelinek <jakub@redhat.com>
PR libffi/45677
diff --git a/libffi/src/arm/ffi.c b/libffi/src/arm/ffi.c
index f6a64758f73..9a0a53c83a9 100644
--- a/libffi/src/arm/ffi.c
+++ b/libffi/src/arm/ffi.c
@@ -29,12 +29,20 @@
#include <stdlib.h>
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments */
+/* Forward declares. */
+static int vfp_type_p (ffi_type *);
+static void layout_vfp_args (ffi_cif *);
-void ffi_prep_args(char *stack, extended_cif *ecif)
+/* ffi_prep_args is called by the assembly routine once stack space
+ has been allocated for the function's arguments
+
+ The vfp_space parameter is the load area for VFP regs, the return
+ value is cif->vfp_used (word bitset of VFP regs used for passing
+ arguments). These are only used for the VFP hard-float ABI.
+*/
+int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
{
- register unsigned int i;
+ register unsigned int i, vi = 0;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
@@ -54,6 +62,21 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
{
size_t z;
+ /* Allocated in VFP registers. */
+ if (ecif->cif->abi == FFI_VFP
+ && vi < ecif->cif->vfp_nargs && vfp_type_p (*p_arg))
+ {
+ float* vfp_slot = vfp_space + ecif->cif->vfp_args[vi++];
+ if ((*p_arg)->type == FFI_TYPE_FLOAT)
+ *((float*)vfp_slot) = *((float*)*p_argv);
+ else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+ *((double*)vfp_slot) = *((double*)*p_argv);
+ else
+ memcpy(vfp_slot, *p_argv, (*p_arg)->size);
+ p_argv++;
+ continue;
+ }
+
/* Align if necessary */
if (((*p_arg)->alignment - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
@@ -103,13 +126,15 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
p_argv++;
argp += z;
}
-
- return;
+
+ /* Indicate the VFP registers used. */
+ return ecif->cif->vfp_used;
}
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
+ int type_code;
/* Round the stack up to a multiple of 8 bytes. This isn't needed
everywhere, but it is on some platforms, and it doesn't harm anything
when it isn't needed. */
@@ -130,7 +155,14 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
break;
case FFI_TYPE_STRUCT:
- if (cif->rtype->size <= 4)
+ if (cif->abi == FFI_VFP
+ && (type_code = vfp_type_p (cif->rtype)) != 0)
+ {
+ /* A Composite Type passed in VFP registers, either
+ FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
+ cif->flags = (unsigned) type_code;
+ }
+ else if (cif->rtype->size <= 4)
/* A Composite Type not larger than 4 bytes is returned in r0. */
cif->flags = (unsigned)FFI_TYPE_INT;
else
@@ -145,11 +177,18 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
break;
}
+ /* Map out the register placements of VFP register args.
+ The VFP hard-float calling conventions are slightly more sophisticated than
+ the base calling conventions, so we do it here instead of in ffi_prep_args(). */
+ if (cif->abi == FFI_VFP)
+ layout_vfp_args (cif);
+
return FFI_OK;
}
-extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
- unsigned, unsigned, unsigned *, void (*fn)(void));
+/* Prototypes for assembly functions, in sysv.S */
+extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
+extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
@@ -157,6 +196,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
int small_struct = (cif->flags == FFI_TYPE_INT
&& cif->rtype->type == FFI_TYPE_STRUCT);
+ int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
+ || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
ecif.cif = cif;
ecif.avalue = avalue;
@@ -173,38 +214,51 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
}
else if (small_struct)
ecif.rvalue = &temp;
+ else if (vfp_struct)
+ {
+ /* Largest case is double x 4. */
+ ecif.rvalue = alloca(32);
+ }
else
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_SYSV:
- ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
- fn);
+ ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
+ break;
+ case FFI_VFP:
+ ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
break;
+
default:
FFI_ASSERT(0);
break;
}
if (small_struct)
memcpy (rvalue, &temp, cif->rtype->size);
+ else if (vfp_struct)
+ memcpy (rvalue, ecif.rvalue, cif->rtype->size);
}
/** private members **/
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
- void** args, ffi_cif* cif);
+ void** args, ffi_cif* cif, float *vfp_stack);
void ffi_closure_SYSV (ffi_closure *);
+void ffi_closure_VFP (ffi_closure *);
+
/* This function is jumped to by the trampoline */
unsigned int
-ffi_closure_SYSV_inner (closure, respp, args)
+ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
ffi_closure *closure;
void **respp;
void *args;
+ void *vfp_args;
{
// our various things...
ffi_cif *cif;
@@ -219,7 +273,7 @@ ffi_closure_SYSV_inner (closure, respp, args)
* a structure, it will re-set RESP to point to the
* structure return address. */
- ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
+ ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
(closure->fun) (cif, *respp, arg_area, closure->user_data);
@@ -229,10 +283,12 @@ ffi_closure_SYSV_inner (closure, respp, args)
/*@-exportheader@*/
static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
- void **avalue, ffi_cif *cif)
+ void **avalue, ffi_cif *cif,
+ /* Used only under VFP hard-float ABI. */
+ float *vfp_stack)
/*@=exportheader@*/
{
- register unsigned int i;
+ register unsigned int i, vi = 0;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
@@ -249,8 +305,16 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
{
size_t z;
-
- size_t alignment = (*p_arg)->alignment;
+ size_t alignment;
+
+ if (cif->abi == FFI_VFP
+ && vi < cif->vfp_nargs && vfp_type_p (*p_arg))
+ {
+ *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
+ continue;
+ }
+
+ alignment = (*p_arg)->alignment;
if (alignment < 4)
alignment = 4;
/* Align if necessary */
@@ -295,10 +359,17 @@ ffi_prep_closure_loc (ffi_closure* closure,
void *user_data,
void *codeloc)
{
- FFI_ASSERT (cif->abi == FFI_SYSV);
+ void (*closure_func)(ffi_closure*) = NULL;
+ if (cif->abi == FFI_SYSV)
+ closure_func = &ffi_closure_SYSV;
+ else if (cif->abi == FFI_VFP)
+ closure_func = &ffi_closure_VFP;
+ else
+ FFI_ASSERT (0);
+
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
- &ffi_closure_SYSV, \
+ closure_func, \
codeloc);
closure->cif = cif;
@@ -307,3 +378,123 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_OK;
}
+
+/* Below are routines for VFP hard-float support. */
+
+static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
+{
+ switch (t->type)
+ {
+ case FFI_TYPE_FLOAT:
+ case FFI_TYPE_DOUBLE:
+ *elt = (int) t->type;
+ *elnum = 1;
+ return 1;
+
+ case FFI_TYPE_STRUCT_VFP_FLOAT:
+ *elt = FFI_TYPE_FLOAT;
+ *elnum = t->size / sizeof (float);
+ return 1;
+
+ case FFI_TYPE_STRUCT_VFP_DOUBLE:
+ *elt = FFI_TYPE_DOUBLE;
+ *elnum = t->size / sizeof (double);
+ return 1;
+
+ case FFI_TYPE_STRUCT:;
+ {
+ int base_elt = 0, total_elnum = 0;
+ ffi_type **el = t->elements;
+ while (*el)
+ {
+ int el_elt = 0, el_elnum = 0;
+ if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
+ || (base_elt && base_elt != el_elt)
+ || total_elnum + el_elnum > 4)
+ return 0;
+ base_elt = el_elt;
+ total_elnum += el_elnum;
+ el++;
+ }
+ *elnum = total_elnum;
+ *elt = base_elt;
+ return 1;
+ }
+ default: ;
+ }
+ return 0;
+}
+
+static int vfp_type_p (ffi_type *t)
+{
+ int elt, elnum;
+ if (rec_vfp_type_p (t, &elt, &elnum))
+ {
+ if (t->type == FFI_TYPE_STRUCT)
+ {
+ if (elnum == 1)
+ t->type = elt;
+ else
+ t->type = (elt == FFI_TYPE_FLOAT
+ ? FFI_TYPE_STRUCT_VFP_FLOAT
+ : FFI_TYPE_STRUCT_VFP_DOUBLE);
+ }
+ return (int) t->type;
+ }
+ return 0;
+}
+
+static void place_vfp_arg (ffi_cif *cif, ffi_type *t)
+{
+ int reg = cif->vfp_reg_free;
+ int nregs = t->size / sizeof (float);
+ int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT
+ || t->type == FFI_TYPE_FLOAT) ? 1 : 2);
+ /* Align register number. */
+ if ((reg & 1) && align == 2)
+ reg++;
+ while (reg + nregs <= 16)
+ {
+ int s, new_used = 0;
+ for (s = reg; s < reg + nregs; s++)
+ {
+ new_used |= (1 << s);
+ if (cif->vfp_used & (1 << s))
+ {
+ reg += align;
+ goto next_reg;
+ }
+ }
+ /* Found regs to allocate. */
+ cif->vfp_used |= new_used;
+ cif->vfp_args[cif->vfp_nargs++] = reg;
+
+ /* Update vfp_reg_free. */
+ if (cif->vfp_used & (1 << cif->vfp_reg_free))
+ {
+ reg += nregs;
+ while (cif->vfp_used & (1 << reg))
+ reg += 1;
+ cif->vfp_reg_free = reg;
+ }
+ return;
+ next_reg: ;
+ }
+}
+
+static void layout_vfp_args (ffi_cif *cif)
+{
+ int i;
+ /* Init VFP fields */
+ cif->vfp_used = 0;
+ cif->vfp_nargs = 0;
+ cif->vfp_reg_free = 0;
+ memset (cif->vfp_args, -1, 16); /* Init to -1. */
+
+ for (i = 0; i < cif->nargs; i++)
+ {
+ ffi_type *t = cif->arg_types[i];
+ if (vfp_type_p (t))
+ place_vfp_arg (cif, t);
+ }
+}
diff --git a/libffi/src/arm/ffitarget.h b/libffi/src/arm/ffitarget.h
index a9574266954..ce25b23f5a3 100644
--- a/libffi/src/arm/ffitarget.h
+++ b/libffi/src/arm/ffitarget.h
@@ -1,5 +1,7 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ Copyright (c) 2010 CodeSourcery
+
Target configuration macros for ARM.
Permission is hereby granted, free of charge, to any person obtaining
@@ -34,11 +36,25 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
+ FFI_VFP,
+ FFI_LAST_ABI,
+#ifdef __ARM_PCS_VFP
+ FFI_DEFAULT_ABI = FFI_VFP,
+#else
FFI_DEFAULT_ABI = FFI_SYSV,
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+#endif
} ffi_abi;
#endif
+#define FFI_EXTRA_CIF_FIELDS \
+ int vfp_used; \
+ short vfp_reg_free, vfp_nargs; \
+ signed char vfp_args[16] \
+
+/* Internally used. */
+#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1)
+#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
+
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
diff --git a/libffi/src/arm/sysv.S b/libffi/src/arm/sysv.S
index 90643185c7f..7bce72712bb 100644
--- a/libffi/src/arm/sysv.S
+++ b/libffi/src/arm/sysv.S
@@ -142,12 +142,11 @@ _L__\name:
.endm
- @ r0: ffi_prep_args
+ @ r0: fn
@ r1: &ecif
@ r2: cif->bytes
@ r3: fig->flags
@ sp+0: ecif.rvalue
- @ sp+4: fn
@ This assumes we are using gas.
ARM_FUNC_START ffi_call_SYSV
@@ -162,24 +161,23 @@ ARM_FUNC_START ffi_call_SYSV
sub sp, fp, r2
@ Place all of the ffi_prep_args in position
- mov ip, r0
mov r0, sp
@ r1 already set
@ Call ffi_prep_args(stack, &ecif)
- call_reg(ip)
+ bl ffi_prep_args
@ move first 4 parameters in registers
ldmia sp, {r0-r3}
@ and adjust stack
- ldr ip, [fp, #8]
- cmp ip, #16
- movhs ip, #16
- add sp, sp, ip
+ sub lr, fp, sp @ cif->bytes == fp - sp
+ ldr ip, [fp] @ load fn() in advance
+ cmp lr, #16
+ movhs lr, #16
+ add sp, sp, lr
@ call (fn) (...)
- ldr ip, [fp, #28]
call_reg(ip)
@ Remove the space we pushed for the args
@@ -230,6 +228,101 @@ LSYM(Lepilogue):
UNWIND .fnend
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+ @ r0: fn
+ @ r1: &ecif
+ @ r2: cif->bytes
+ @ r3: fig->flags
+ @ sp+0: ecif.rvalue
+
+ARM_FUNC_START ffi_call_VFP
+ @ Save registers
+ stmfd sp!, {r0-r3, fp, lr}
+ UNWIND .save {r0-r3, fp, lr}
+ mov fp, sp
+ UNWIND .setfp fp, sp
+
+ @ Make room for all of the new args.
+ sub sp, sp, r2
+
+ @ Make room for loading VFP args
+ sub sp, sp, #64
+
+ @ Place all of the ffi_prep_args in position
+ mov r0, sp
+ @ r1 already set
+ sub r2, fp, #64 @ VFP scratch space
+
+ @ Call ffi_prep_args(stack, &ecif, vfp_space)
+ bl ffi_prep_args
+
+ @ Load VFP register args if needed
+ cmp r0, #0
+ beq LSYM(Lbase_args)
+
+ @ Load only d0 if possible
+ cmp r0, #3
+ sub ip, fp, #64
+ flddle d0, [ip]
+ fldmiadgt ip, {d0-d7}
+
+LSYM(Lbase_args):
+ @ move first 4 parameters in registers
+ ldmia sp, {r0-r3}
+
+ @ and adjust stack
+ sub lr, ip, sp @ cif->bytes == (fp - 64) - sp
+ ldr ip, [fp] @ load fn() in advance
+ cmp lr, #16
+ movhs lr, #16
+ add sp, sp, lr
+
+ @ call (fn) (...)
+ call_reg(ip)
+
+ @ Remove the space we pushed for the args
+ mov sp, fp
+
+ @ Load r2 with the pointer to storage for
+ @ the return value
+ ldr r2, [sp, #24]
+
+ @ Load r3 with the return type code
+ ldr r3, [sp, #12]
+
+ @ If the return value pointer is NULL,
+ @ assume no return value.
+ cmp r2, #0
+ beq LSYM(Lepilogue_vfp)
+
+ cmp r3, #FFI_TYPE_INT
+ streq r0, [r2]
+ beq LSYM(Lepilogue_vfp)
+
+ cmp r3, #FFI_TYPE_SINT64
+ stmeqia r2, {r0, r1}
+ beq LSYM(Lepilogue_vfp)
+
+ cmp r3, #FFI_TYPE_FLOAT
+ fstseq s0, [r2]
+ beq LSYM(Lepilogue_vfp)
+
+ cmp r3, #FFI_TYPE_DOUBLE
+ fstdeq d0, [r2]
+ beq LSYM(Lepilogue_vfp)
+
+ cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT
+ cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
+ fstmiadeq r2, {d0-d3}
+
+LSYM(Lepilogue_vfp):
+ RETLDM "r0-r3,fp"
+
+.ffi_call_VFP_end:
+ UNWIND .fnend
+ .size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
+
+
/*
unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (closure, respp, args)
@@ -302,6 +395,68 @@ ARM_FUNC_START ffi_closure_SYSV
UNWIND .fnend
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+ARM_FUNC_START ffi_closure_VFP
+ fstmfdd sp!, {d0-d7}
+ @ r0-r3, then d0-d7
+ UNWIND .pad #80
+ add ip, sp, #80
+ stmfd sp!, {ip, lr}
+ UNWIND .save {r0, lr}
+ add r2, sp, #72
+ add r3, sp, #8
+ .pad #72
+ sub sp, sp, #72
+ str sp, [sp, #64]
+ add r1, sp, #64
+ bl ffi_closure_SYSV_inner
+
+ cmp r0, #FFI_TYPE_INT
+ beq .Lretint_vfp
+
+ cmp r0, #FFI_TYPE_FLOAT
+ beq .Lretfloat_vfp
+
+ cmp r0, #FFI_TYPE_DOUBLE
+ cmpne r0, #FFI_TYPE_LONGDOUBLE
+ beq .Lretdouble_vfp
+
+ cmp r0, #FFI_TYPE_SINT64
+ beq .Lretlonglong_vfp
+
+ cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT
+ beq .Lretfloat_struct_vfp
+
+ cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
+ beq .Lretdouble_struct_vfp
+
+.Lclosure_epilogue_vfp:
+ add sp, sp, #72
+ ldmfd sp, {sp, pc}
+
+.Lretfloat_vfp:
+ flds s0, [sp]
+ b .Lclosure_epilogue_vfp
+.Lretdouble_vfp:
+ fldd d0, [sp]
+ b .Lclosure_epilogue_vfp
+.Lretint_vfp:
+ ldr r0, [sp]
+ b .Lclosure_epilogue_vfp
+.Lretlonglong_vfp:
+ ldmia sp, {r0, r1}
+ b .Lclosure_epilogue_vfp
+.Lretfloat_struct_vfp:
+ fldmiad sp, {d0-d1}
+ b .Lclosure_epilogue_vfp
+.Lretdouble_struct_vfp:
+ fldmiad sp, {d0-d3}
+ b .Lclosure_epilogue_vfp
+
+.ffi_closure_VFP_end:
+ UNWIND .fnend
+ .size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
+
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",%progbits
#endif
diff --git a/libffi/testsuite/lib/libffi-dg.exp b/libffi/testsuite/lib/libffi-dg.exp
index bd5a7c84f48..82d6652c183 100644
--- a/libffi/testsuite/lib/libffi-dg.exp
+++ b/libffi/testsuite/lib/libffi-dg.exp
@@ -272,6 +272,56 @@ proc dg-xfail-if { args } {
}
}
+proc check-flags { args } {
+
+ # The args are within another list; pull them out.
+ set args [lindex $args 0]
+
+ # The next two arguments are optional. If they were not specified,
+ # use the defaults.
+ if { [llength $args] == 2 } {
+ lappend $args [list "*"]
+ }
+ if { [llength $args] == 3 } {
+ lappend $args [list ""]
+ }
+
+ # If the option strings are the defaults, or the same as the
+ # defaults, there is no need to call check_conditional_xfail to
+ # compare them to the actual options.
+ if { [string compare [lindex $args 2] "*"] == 0
+ && [string compare [lindex $args 3] "" ] == 0 } {
+ set result 1
+ } else {
+ # The target list might be an effective-target keyword, so replace
+ # the original list with "*-*-*", since we already know it matches.
+ set result [check_conditional_xfail [lreplace $args 1 1 "*-*-*"]]
+ }
+
+ return $result
+}
+
+proc dg-skip-if { args } {
+ # Verify the number of arguments. The last two are optional.
+ set args [lreplace $args 0 0]
+ if { [llength $args] < 2 || [llength $args] > 4 } {
+ error "dg-skip-if 2: need 2, 3, or 4 arguments"
+ }
+
+ # Don't bother if we're already skipping the test.
+ upvar dg-do-what dg-do-what
+ if { [lindex ${dg-do-what} 1] == "N" } {
+ return
+ }
+
+ set selector [list target [lindex $args 1]]
+ if { [dg-process-target $selector] == "S" } {
+ if [check-flags $args] {
+ upvar dg-do-what dg-do-what
+ set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+ }
+ }
+}
# We need to make sure that additional_files and additional_sources
# are both cleared out after every test. It is not enough to clear
diff --git a/libffi/testsuite/libffi.call/cls_double_va.c b/libffi/testsuite/libffi.call/cls_double_va.c
index 0695874b3ce..62bebbd7069 100644
--- a/libffi/testsuite/libffi.call/cls_double_va.c
+++ b/libffi/testsuite/libffi.call/cls_double_va.c
@@ -6,6 +6,8 @@
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
/* { dg-output "" { xfail avr32*-*-* } } */
+/* { dg-skip-if "" arm*-*-* { "-mfloat-abi=hard" } { "" } } */
+
#include "ffitest.h"
static void
diff --git a/libffi/testsuite/libffi.call/cls_longdouble_va.c b/libffi/testsuite/libffi.call/cls_longdouble_va.c
index 38564cb086b..b33b2b72214 100644
--- a/libffi/testsuite/libffi.call/cls_longdouble_va.c
+++ b/libffi/testsuite/libffi.call/cls_longdouble_va.c
@@ -6,6 +6,8 @@
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
/* { dg-output "" { xfail avr32*-*-* x86_64-*-mingw* } } */
+/* { dg-skip-if "" arm*-*-* { "-mfloat-abi=hard" } { "" } } */
+
#include "ffitest.h"
static void
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 8585db51634..3d00793c9fd 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,9 @@
+2010-10-29 Ian Lance Taylor <iant@google.com>
+
+ * setproctitle.c: Add space after function name in @deftypefn
+ comment.
+ * functions.texi: Rebuild.
+
2010-10-26 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* aclocal.m4 (AC_LANG_FUNC_LINK_TRY(C)): Delete.
diff --git a/libiberty/functions.texi b/libiberty/functions.texi
index e074ba716f8..af8c4bf6da1 100644
--- a/libiberty/functions.texi
+++ b/libiberty/functions.texi
@@ -1147,7 +1147,7 @@ environment. This implementation is not safe for multithreaded code.
@end deftypefn
@c setproctitle.c:30
-@deftypefn Supplemental void setproctitle(const char *@var{fmt} ...)
+@deftypefn Supplemental void setproctitle (const char *@var{fmt} ...)
Set the title of a process to @var{fmt}. va args not supported for now,
but defined for compatibility with BSD.
diff --git a/libiberty/setproctitle.c b/libiberty/setproctitle.c
index b176b41f949..734af2eca6e 100644
--- a/libiberty/setproctitle.c
+++ b/libiberty/setproctitle.c
@@ -27,7 +27,7 @@ Boston, MA 02110-1301, USA. */
/*
-@deftypefn Supplemental void setproctitle(const char *@var{fmt} ...)
+@deftypefn Supplemental void setproctitle (const char *@var{fmt} ...)
Set the title of a process to @var{fmt}. va args not supported for now,
but defined for compatibility with BSD.
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 685df0937b1..8522b62f487 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,53 @@
+2010-10-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/bits/stl_function.h (_Select1st<>::operator()): Add
+ templatized overloads.
+ * include/bits/hashtable_policy.h (_Select1st): Remove; revert
+ everything to std::_Select1st.
+ * include/bits/unordered_map.h: Likewise.
+
+2010-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/44436 (partial)
+ * include/bits/hashtable.h (_Hashtable<>::insert(value_type&&),
+ insert(_Pair&&), insert(const_iterator, value_type&&),
+ insert(const_iterator, _Pair&&)): Add.
+ (_M_allocate_node, _M_insert, _M_insert_bucket): Templatize.
+ * include/bits/hashtable_policy.h (__detail::_Select1st): Add; use
+ it throughout.
+ (_Map_base<>::operator[](_Key&&)): Add.
+ * include/bits/unordered_map.h: Use __detail::_Select1st throughout.
+ * include/debug/unordered_map: Update.
+ * include/debug/unordered_set: Likewise.
+ * include/profile/unordered_map: Likewise.
+ * include/profile/unordered_set: Likewise.
+ * testsuite/util/testsuite_rvalref.h (struct hash<rvalstruct>): Add;
+ minor tweaks throughout, use deleted special members.
+ * testsuite/23_containers/unordered_map/insert/map_single_move-1.cc:
+ New.
+ * testsuite/23_containers/unordered_map/insert/map_single_move-2.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_map/insert/array_syntax_move.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_multimap/insert/
+ multimap_single_move-1.cc: Likewise.
+ * testsuite/23_containers/unordered_multimap/insert/
+ multimap_single_move-2.cc: Likewise.
+ * testsuite/23_containers/unordered_set/insert/set_single_move.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_multiset/insert/
+ multiset_single_move.cc: Likewise.
+
+ * testsuite/23_containers/unordered_map/insert/array_syntax.cc:
+ Minor cosmetic changes.
+
+2010-10-27 Jason Merrill <jason@redhat.com>
+
+ * include/std/type_traits (is_literal_type): New.
+ * testsuite/20_util/declval/requirements/1_neg.cc: Adjust.
+ * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust.
+ * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Adjust.
+
2010-10-26 Paolo Carlini <paolo.carlini@oracle.com>
* testsuite/lib/libstdc++.exp ([check_v3_target_normal_mode]): Add.
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index dd8c1c22349..343a12267fd 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -178,9 +178,10 @@ namespace std
size_type _M_begin_bucket_index; // First non-empty bucket.
size_type _M_element_count;
_RehashPolicy _M_rehash_policy;
-
- _Node*
- _M_allocate_node(const value_type& __v);
+
+ template<typename... _Args>
+ _Node*
+ _M_allocate_node(_Args&&... __args);
void
_M_deallocate_node(_Node* __n);
@@ -360,11 +361,27 @@ namespace std
std::pair<const_iterator, const_iterator>
equal_range(const key_type& __k) const;
- private: // Find, insert and erase helper functions
- // ??? This dispatching is a workaround for the fact that we don't
- // have partial specialization of member templates; it would be
- // better to just specialize insert on __unique_keys. There may be a
- // cleaner workaround.
+ private:
+ // Find, insert and erase helper functions
+ _Node*
+ _M_find_node(_Node*, const key_type&,
+ typename _Hashtable::_Hash_code_type) const;
+
+ template<typename _Pair>
+ iterator
+ _M_insert_bucket(_Pair&&, size_type,
+ typename _Hashtable::_Hash_code_type);
+
+ template<typename _Pair>
+ std::pair<iterator, bool>
+ _M_insert(_Pair&&, std::true_type);
+
+ template<typename _Pair>
+ iterator
+ _M_insert(_Pair&&, std::false_type);
+
+ public:
+ // Insert and erase
typedef typename std::conditional<__unique_keys,
std::pair<iterator, bool>,
iterator>::type
@@ -376,30 +393,39 @@ namespace std
>::type
_Insert_Conv_Type;
- _Node*
- _M_find_node(_Node*, const key_type&,
- typename _Hashtable::_Hash_code_type) const;
-
- iterator
- _M_insert_bucket(const value_type&, size_type,
- typename _Hashtable::_Hash_code_type);
-
- std::pair<iterator, bool>
- _M_insert(const value_type&, std::true_type);
+ _Insert_Return_Type
+ insert(const value_type& __v)
+ { return _M_insert(__v, std::integral_constant<bool, __unique_keys>()); }
iterator
- _M_insert(const value_type&, std::false_type);
+ insert(const_iterator, const value_type& __v)
+ { return _Insert_Conv_Type()(insert(__v)); }
- public:
- // Insert and erase
_Insert_Return_Type
- insert(const value_type& __v)
- { return _M_insert(__v, std::integral_constant<bool,
- __unique_keys>()); }
+ insert(value_type&& __v)
+ { return _M_insert(std::move(__v),
+ std::integral_constant<bool, __unique_keys>()); }
iterator
- insert(const_iterator, const value_type& __v)
- { return iterator(_Insert_Conv_Type()(this->insert(__v))); }
+ insert(const_iterator, value_type&& __v)
+ { return _Insert_Conv_Type()(insert(std::move(__v))); }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<!__constant_iterators
+ && std::is_convertible<_Pair,
+ value_type>::value>::type>
+ _Insert_Return_Type
+ insert(_Pair&& __v)
+ { return _M_insert(std::forward<_Pair>(__v),
+ std::integral_constant<bool, __unique_keys>()); }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<!__constant_iterators
+ && std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator, _Pair&& __v)
+ { return _Insert_Conv_Type()(insert(std::forward<_Pair>(__v))); }
template<typename _InputIterator>
void
@@ -438,26 +464,27 @@ namespace std
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
- typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::_Node*
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_allocate_node(const value_type& __v)
- {
- _Node* __n = _M_node_allocator.allocate(1);
- __try
- {
- _M_node_allocator.construct(__n, __v);
- __n->_M_next = 0;
- return __n;
- }
- __catch(...)
- {
- _M_node_allocator.deallocate(__n, 1);
- __throw_exception_again;
- }
- }
+ template<typename... _Args>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::_Node*
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_allocate_node(_Args&&... __args)
+ {
+ _Node* __n = _M_node_allocator.allocate(1);
+ __try
+ {
+ _M_node_allocator.construct(__n, std::forward<_Args>(__args)...);
+ __n->_M_next = 0;
+ return __n;
+ }
+ __catch(...)
+ {
+ _M_node_allocator.deallocate(__n, 1);
+ __throw_exception_again;
+ }
+ }
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
@@ -871,111 +898,117 @@ namespace std
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
- typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::iterator
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_insert_bucket(const value_type& __v, size_type __n,
- typename _Hashtable::_Hash_code_type __code)
- {
- std::pair<bool, std::size_t> __do_rehash
- = _M_rehash_policy._M_need_rehash(_M_bucket_count,
- _M_element_count, 1);
+ template<typename _Pair>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::iterator
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_insert_bucket(_Pair&& __v, size_type __n,
+ typename _Hashtable::_Hash_code_type __code)
+ {
+ std::pair<bool, std::size_t> __do_rehash
+ = _M_rehash_policy._M_need_rehash(_M_bucket_count,
+ _M_element_count, 1);
- // Allocate the new node before doing the rehash so that we don't
- // do a rehash if the allocation throws.
- _Node* __new_node = _M_allocate_node(__v);
+ if (__do_rehash.first)
+ {
+ const key_type& __k = this->_M_extract(__v);
+ __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
+ }
- __try
- {
- if (__do_rehash.first)
- {
- const key_type& __k = this->_M_extract(__v);
- __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
+ // Allocate the new node before doing the rehash so that we don't
+ // do a rehash if the allocation throws.
+ _Node* __new_node = _M_allocate_node(std::forward<_Pair>(__v));
+
+ __try
+ {
+ if (__do_rehash.first)
_M_rehash(__do_rehash.second);
- }
- __new_node->_M_next = _M_buckets[__n];
- this->_M_store_code(__new_node, __code);
- _M_buckets[__n] = __new_node;
- ++_M_element_count;
- if (__n < _M_begin_bucket_index)
- _M_begin_bucket_index = __n;
- return iterator(__new_node, _M_buckets + __n);
- }
- __catch(...)
- {
- _M_deallocate_node(__new_node);
- __throw_exception_again;
- }
- }
+ __new_node->_M_next = _M_buckets[__n];
+ this->_M_store_code(__new_node, __code);
+ _M_buckets[__n] = __new_node;
+ ++_M_element_count;
+ if (__n < _M_begin_bucket_index)
+ _M_begin_bucket_index = __n;
+ return iterator(__new_node, _M_buckets + __n);
+ }
+ __catch(...)
+ {
+ _M_deallocate_node(__new_node);
+ __throw_exception_again;
+ }
+ }
// Insert v if no element with its key is already present.
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
- std::pair<typename _Hashtable<_Key, _Value, _Allocator,
- _ExtractKey, _Equal, _H1,
- _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::iterator, bool>
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_insert(const value_type& __v, std::true_type)
- {
- const key_type& __k = this->_M_extract(__v);
- typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
- size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
-
- if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
- return std::make_pair(iterator(__p, _M_buckets + __n), false);
- return std::make_pair(_M_insert_bucket(__v, __n, __code), true);
- }
+ template<typename _Pair>
+ std::pair<typename _Hashtable<_Key, _Value, _Allocator,
+ _ExtractKey, _Equal, _H1,
+ _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::iterator, bool>
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_insert(_Pair&& __v, std::true_type)
+ {
+ const key_type& __k = this->_M_extract(__v);
+ typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
+ size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
+
+ if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
+ return std::make_pair(iterator(__p, _M_buckets + __n), false);
+ return std::make_pair(_M_insert_bucket(std::forward<_Pair>(__v),
+ __n, __code), true);
+ }
// Insert v unconditionally.
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
- typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::iterator
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_insert(const value_type& __v, std::false_type)
- {
- std::pair<bool, std::size_t> __do_rehash
- = _M_rehash_policy._M_need_rehash(_M_bucket_count,
- _M_element_count, 1);
- if (__do_rehash.first)
- _M_rehash(__do_rehash.second);
+ template<typename _Pair>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::iterator
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_insert(_Pair&& __v, std::false_type)
+ {
+ std::pair<bool, std::size_t> __do_rehash
+ = _M_rehash_policy._M_need_rehash(_M_bucket_count,
+ _M_element_count, 1);
+ if (__do_rehash.first)
+ _M_rehash(__do_rehash.second);
- const key_type& __k = this->_M_extract(__v);
- typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
- size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
+ const key_type& __k = this->_M_extract(__v);
+ typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
+ size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
- // First find the node, avoid leaking new_node if compare throws.
- _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
- _Node* __new_node = _M_allocate_node(__v);
+ // First find the node, avoid leaking new_node if compare throws.
+ _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
+ _Node* __new_node = _M_allocate_node(std::forward<_Pair>(__v));
- if (__prev)
- {
- __new_node->_M_next = __prev->_M_next;
- __prev->_M_next = __new_node;
- }
- else
- {
- __new_node->_M_next = _M_buckets[__n];
- _M_buckets[__n] = __new_node;
- if (__n < _M_begin_bucket_index)
- _M_begin_bucket_index = __n;
- }
- this->_M_store_code(__new_node, __code);
+ if (__prev)
+ {
+ __new_node->_M_next = __prev->_M_next;
+ __prev->_M_next = __new_node;
+ }
+ else
+ {
+ __new_node->_M_next = _M_buckets[__n];
+ _M_buckets[__n] = __new_node;
+ if (__n < _M_begin_bucket_index)
+ _M_begin_bucket_index = __n;
+ }
+ this->_M_store_code(__new_node, __code);
- ++_M_element_count;
- return iterator(__new_node, _M_buckets + __n);
- }
+ ++_M_element_count;
+ return iterator(__new_node, _M_buckets + __n);
+ }
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 694d0ffdeb4..d8d2af5d64e 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -497,7 +497,7 @@ namespace __detail
// the form pair<T1, T2> and a key extraction policy that returns the
// first part of the pair, the hashtable gets a mapped_type typedef.
// If it satisfies those criteria and also has unique keys, then it
- // also gets an operator[].
+ // also gets an operator[].
template<typename _Key, typename _Value, typename _Ex, bool __unique,
typename _Hashtable>
struct _Map_base { };
@@ -516,6 +516,9 @@ namespace __detail
mapped_type&
operator[](const _Key& __k);
+ mapped_type&
+ operator[](_Key&& __k);
+
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 761. unordered_map needs an at() member function.
mapped_type&
@@ -548,6 +551,26 @@ namespace __detail
typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
true, _Hashtable>::mapped_type&
_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
+ operator[](_Key&& __k)
+ {
+ _Hashtable* __h = static_cast<_Hashtable*>(this);
+ typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
+ std::size_t __n = __h->_M_bucket_index(__k, __code,
+ __h->_M_bucket_count);
+
+ typename _Hashtable::_Node* __p =
+ __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
+ if (!__p)
+ return __h->_M_insert_bucket(std::make_pair(std::move(__k),
+ mapped_type()),
+ __n, __code)->second;
+ return (__p->_M_v).second;
+ }
+
+ template<typename _Key, typename _Pair, typename _Hashtable>
+ typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
+ true, _Hashtable>::mapped_type&
+ _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
at(const _Key& __k)
{
_Hashtable* __h = static_cast<_Hashtable*>(this);
diff --git a/libstdc++-v3/include/bits/stl_function.h b/libstdc++-v3/include/bits/stl_function.h
index fd9c3589d69..a5f5e255825 100644
--- a/libstdc++-v3/include/bits/stl_function.h
+++ b/libstdc++-v3/include/bits/stl_function.h
@@ -487,6 +487,18 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
const typename _Pair::first_type&
operator()(const _Pair& __x) const
{ return __x.first; }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Pair2>
+ typename _Pair2::first_type&
+ operator()(_Pair2& __x) const
+ { return __x.first; }
+
+ template<typename _Pair2>
+ const typename _Pair2::first_type&
+ operator()(const _Pair2& __x) const
+ { return __x.first; }
+#endif
};
template<typename _Pair>
diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map
index 2e2f9122ee0..6f37e040a26 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -190,6 +190,28 @@ namespace __debug
return iterator(__res.first, this);
}
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ std::pair<iterator, bool>
+ insert(_Pair&& __obj)
+ {
+ typedef std::pair<typename _Base::iterator, bool> __pair_type;
+ __pair_type __res = _Base::insert(std::forward<_Pair>(__obj));
+ return std::make_pair(iterator(__res.first, this), __res.second);
+ }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator, _Pair&& __obj)
+ {
+ typedef std::pair<typename _Base::iterator, bool> __pair_type;
+ __pair_type __res = _Base::insert(std::forward<_Pair>(__obj));
+ return iterator(__res.first, this);
+ }
+
void
insert(std::initializer_list<value_type> __l)
{ _Base::insert(__l); }
@@ -444,6 +466,20 @@ namespace __debug
insert(const_iterator, const value_type& __obj)
{ return iterator(_Base::insert(__obj), this); }
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(_Pair&& __obj)
+ { return iterator(_Base::insert(std::forward<_Pair>(__obj)), this); }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator, _Pair&& __obj)
+ { return iterator(_Base::insert(std::forward<_Pair>(__obj)), this); }
+
void
insert(std::initializer_list<value_type> __l)
{ _Base::insert(__l); }
diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set
index ea90c675476..1d42905e236 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -190,6 +190,22 @@ namespace __debug
return iterator(__res.first, this);
}
+ std::pair<iterator, bool>
+ insert(value_type&& __obj)
+ {
+ typedef std::pair<typename _Base::iterator, bool> __pair_type;
+ __pair_type __res = _Base::insert(std::move(__obj));
+ return std::make_pair(iterator(__res.first, this), __res.second);
+ }
+
+ iterator
+ insert(const_iterator, value_type&& __obj)
+ {
+ typedef std::pair<typename _Base::iterator, bool> __pair_type;
+ __pair_type __res = _Base::insert(std::move(__obj));
+ return iterator(__res.first, this);
+ }
+
void
insert(std::initializer_list<value_type> __l)
{ _Base::insert(__l); }
@@ -440,6 +456,14 @@ namespace __debug
insert(const_iterator, const value_type& __obj)
{ return iterator(_Base::insert(__obj), this); }
+ iterator
+ insert(value_type&& __obj)
+ { return iterator(_Base::insert(std::move(__obj)), this); }
+
+ iterator
+ insert(const_iterator, value_type&& __obj)
+ { return iterator(_Base::insert(std::move(__obj)), this); }
+
void
insert(std::initializer_list<value_type> __l)
{ _Base::insert(__l); }
diff --git a/libstdc++-v3/include/profile/unordered_map b/libstdc++-v3/include/profile/unordered_map
index 2dec1f2a268..18563d87508 100644
--- a/libstdc++-v3/include/profile/unordered_map
+++ b/libstdc++-v3/include/profile/unordered_map
@@ -191,6 +191,31 @@ namespace __profile
return __res;
}
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ std::pair<iterator, bool>
+ insert(_Pair&& __obj)
+ {
+ size_type __old_size = _Base::bucket_count();
+ std::pair<iterator, bool> __res
+ = _Base::insert(std::forward<_Pair>(__obj));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator __iter, _Pair&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
template<typename _InputIter>
void
insert(_InputIter __first, _InputIter __last)
@@ -420,11 +445,35 @@ namespace __profile
insert(const_iterator __iter, const value_type& __v)
{
size_type __old_size = _Base::bucket_count();
- iterator __res =_Base::insert(__iter, __v);
+ iterator __res = _Base::insert(__iter, __v);
_M_profile_resize(__old_size, _Base::bucket_count());
return __res;
}
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(_Pair&& __obj)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(std::forward<_Pair>(__obj));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
+ template<typename _Pair, typename = typename
+ std::enable_if<std::is_convertible<_Pair,
+ value_type>::value>::type>
+ iterator
+ insert(const_iterator __iter, _Pair&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
template<typename _InputIter>
void
insert(_InputIter __first, _InputIter __last)
diff --git a/libstdc++-v3/include/profile/unordered_set b/libstdc++-v3/include/profile/unordered_set
index 2dade092024..f46cf5c8bdd 100644
--- a/libstdc++-v3/include/profile/unordered_set
+++ b/libstdc++-v3/include/profile/unordered_set
@@ -174,7 +174,7 @@ namespace __profile
std::pair<iterator, bool>
insert(const value_type& __obj)
{
- size_type __old_size = _Base::bucket_count();
+ size_type __old_size = _Base::bucket_count();
std::pair<iterator, bool> __res = _Base::insert(__obj);
_M_profile_resize(__old_size, _Base::bucket_count());
return __res;
@@ -189,6 +189,24 @@ namespace __profile
return __res;
}
+ std::pair<iterator, bool>
+ insert(value_type&& __obj)
+ {
+ size_type __old_size = _Base::bucket_count();
+ std::pair<iterator, bool> __res = _Base::insert(std::move(__obj));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
+ iterator
+ insert(const_iterator __iter, value_type&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::move(__v));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
template<typename _InputIter>
void
insert(_InputIter __first, _InputIter __last)
@@ -406,13 +424,31 @@ namespace __profile
iterator
insert(const_iterator __iter, const value_type& __v)
- {
+ {
size_type __old_size = _Base::bucket_count();
iterator __res = _Base::insert(__iter, __v);
_M_profile_resize(__old_size, _Base::bucket_count());
return __res;
}
+ iterator
+ insert(value_type&& __obj)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(std::move(__obj));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
+ iterator
+ insert(const_iterator __iter, value_type&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::move(__v));
+ _M_profile_resize(__old_size, _Base::bucket_count());
+ return __res;
+ }
+
template<typename _InputIter>
void
insert(_InputIter __first, _InputIter __last)
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc
index 11fddbb39dd..91f58799a58 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax.cc
@@ -29,25 +29,24 @@ void test01()
bool test __attribute__((unused)) = true;
typedef std::unordered_map<std::string, int> Map;
- typedef std::pair<const std::string, int> Pair;
Map m;
- VERIFY(m.empty());
+ VERIFY( m.empty() );
m["red"] = 17;
- VERIFY(m.size() == 1);
- VERIFY(m.begin()->first == "red");
- VERIFY(m.begin()->second == 17);
- VERIFY(m["red"] == 17);
+ VERIFY( m.size() == 1 );
+ VERIFY( m.begin()->first == "red" );
+ VERIFY( m.begin()->second == 17 );
+ VERIFY( m["red"] == 17 );
m["blue"] = 9;
- VERIFY(m.size() == 2);
- VERIFY(m["blue"] == 9);
+ VERIFY( m.size() == 2 );
+ VERIFY( m["blue"] == 9 );
m["red"] = 5;
- VERIFY(m.size() == 2);
- VERIFY(m["red"] == 5);
- VERIFY(m["blue"] == 9);
+ VERIFY( m.size() == 2 );
+ VERIFY( m["red"] == 5 );
+ VERIFY( m["blue"] == 9 );
}
int main()
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc
new file mode 100644
index 00000000000..b0729e32712
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/array_syntax_move.cc
@@ -0,0 +1,59 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Array version of insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<rvalstruct, rvalstruct> Map;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ m[rvalstruct(1)] = rvalstruct(17);
+ VERIFY( m.size() == 1 );
+ VERIFY( (m.begin()->first).val == 1 );
+ VERIFY( (m.begin()->second).val == 17 );
+ VERIFY( m[rvalstruct(1)].val == 17 );
+
+ m[rvalstruct(2)] = rvalstruct(9);
+ VERIFY( m.size() == 2 );
+ VERIFY( m[rvalstruct(2)].val == 9 );
+
+ m[rvalstruct(1)] = rvalstruct(5);
+ VERIFY( m.size() == 2 );
+ VERIFY( m[rvalstruct(1)].val == 5 );
+ VERIFY( m[rvalstruct(2)].val == 9 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc
new file mode 100644
index 00000000000..45186ce459b
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-1.cc
@@ -0,0 +1,76 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<int, rvalstruct> Map;
+ typedef std::pair<const int, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty());
+
+ std::pair<Map::iterator, bool> p = m.insert(Pair(1, rvalstruct(3)));
+ VERIFY( p.second );
+ VERIFY( m.size() == 1 );
+ VERIFY( std::distance(m.begin(), m.end()) == 1 );
+ VERIFY( p.first == m.begin() );
+ VERIFY( p.first->first == 1 );
+ VERIFY( (p.first->second).val == 3 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<int, rvalstruct> Map;
+ typedef std::pair<const int, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ std::pair<Map::iterator, bool> p1 = m.insert(Pair(2, rvalstruct(3)));
+ std::pair<Map::iterator, bool> p2 = m.insert(Pair(2, rvalstruct(7)));
+
+ VERIFY( p1.second );
+ VERIFY( !p2.second );
+ VERIFY( m.size() == 1 );
+ VERIFY( p1.first == p2.first );
+ VERIFY( p1.first->first == 2 );
+ VERIFY( (p2.first->second).val == 3 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc
new file mode 100644
index 00000000000..76b6bba0077
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/insert/map_single_move-2.cc
@@ -0,0 +1,79 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<rvalstruct, rvalstruct> Map;
+ typedef std::pair<rvalstruct, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty());
+
+ std::pair<Map::iterator, bool> p = m.insert(Pair(rvalstruct(1),
+ rvalstruct(3)));
+ VERIFY( p.second );
+ VERIFY( m.size() == 1 );
+ VERIFY( std::distance(m.begin(), m.end()) == 1 );
+ VERIFY( p.first == m.begin() );
+ VERIFY( (p.first->first).val == 1 );
+ VERIFY( (p.first->second).val == 3 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_map<rvalstruct, rvalstruct> Map;
+ typedef std::pair<rvalstruct, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ std::pair<Map::iterator, bool> p1 = m.insert(Pair(rvalstruct(2),
+ rvalstruct(3)));
+ std::pair<Map::iterator, bool> p2 = m.insert(Pair(rvalstruct(2),
+ rvalstruct(7)));
+
+ VERIFY( p1.second );
+ VERIFY( !p2.second );
+ VERIFY( m.size() == 1 );
+ VERIFY( p1.first == p2.first );
+ VERIFY( (p1.first->first).val == 2 );
+ VERIFY( (p2.first->second).val == 3 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc
new file mode 100644
index 00000000000..4c933069c46
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-1.cc
@@ -0,0 +1,80 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multimap<int, rvalstruct> Map;
+ typedef std::pair<const int, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ Map::iterator i = m.insert(Pair(1, rvalstruct(3)));
+ VERIFY( m.size() == 1 );
+ VERIFY( std::distance(m.begin(), m.end()) == 1 );
+ VERIFY( i == m.begin() );
+ VERIFY( i->first == 1 );
+ VERIFY( (i->second).val == 3 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multimap<int, rvalstruct> Map;
+ typedef std::pair<const int, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ m.insert(Pair(2, rvalstruct(3)));
+ m.insert(Pair(2, rvalstruct(7)));
+
+ VERIFY( m.size() == 2 );
+ VERIFY( std::distance(m.begin(), m.end()) == 2 );
+
+ Map::iterator i1 = m.begin();
+ Map::iterator i2 = i1;
+ ++i2;
+
+ VERIFY( i1->first == 2 );
+ VERIFY( i2->first == 2 );
+ VERIFY( ((i1->second).val == 3 && (i2->second).val == 7)
+ || ((i1->second).val == 7 && (i2->second).val == 3) );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc
new file mode 100644
index 00000000000..e9008b46156
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/multimap_single_move-2.cc
@@ -0,0 +1,80 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multimap<rvalstruct, rvalstruct> Map;
+ typedef std::pair<rvalstruct, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ Map::iterator i = m.insert(Pair(rvalstruct(1), rvalstruct(3)));
+ VERIFY( m.size() == 1 );
+ VERIFY( std::distance(m.begin(), m.end()) == 1 );
+ VERIFY( i == m.begin() );
+ VERIFY( (i->first).val == 1 );
+ VERIFY( (i->second).val == 3 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multimap<rvalstruct, rvalstruct> Map;
+ typedef std::pair<rvalstruct, rvalstruct> Pair;
+
+ Map m;
+ VERIFY( m.empty() );
+
+ m.insert(Pair(rvalstruct(2), rvalstruct(3)));
+ m.insert(Pair(rvalstruct(2), rvalstruct(7)));
+
+ VERIFY( m.size() == 2 );
+ VERIFY( std::distance(m.begin(), m.end()) == 2 );
+
+ Map::iterator i1 = m.begin();
+ Map::iterator i2 = i1;
+ ++i2;
+
+ VERIFY( (i1->first).val == 2 );
+ VERIFY( (i2->first).val == 2 );
+ VERIFY( ((i1->second).val == 3 && (i2->second).val == 7)
+ || ((i1->second).val == 7 && (i2->second).val == 3) );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc
new file mode 100644
index 00000000000..14b8e16817a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc
@@ -0,0 +1,71 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_set>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multiset<rvalstruct> Set;
+ Set s;
+ VERIFY( s.empty() );
+
+ Set::iterator i = s.insert(rvalstruct(1));
+ VERIFY( s.size() == 1 );
+ VERIFY( std::distance(s.begin(), s.end()) == 1 );
+ VERIFY( i == s.begin() );
+ VERIFY( (*i).val == 1 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_multiset<rvalstruct> Set;
+ Set s;
+ VERIFY( s.empty() );
+
+ s.insert(rvalstruct(2));
+ Set::iterator i = s.insert(rvalstruct(2));
+ VERIFY( s.size() == 2 );
+ VERIFY( std::distance(s.begin(), s.end()) == 2 );
+ VERIFY( (*i).val == 2 );
+
+ Set::iterator i2 = s.begin();
+ ++i2;
+ VERIFY( i == s.begin() || i == i2 );
+ VERIFY( (*(s.begin())).val == 2 && (*i2).val == 2 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc
new file mode 100644
index 00000000000..0b9ad173b0f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/insert/set_single_move.cc
@@ -0,0 +1,69 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2010-10-27 Paolo Carlini <paolo.carlini@oracle.com>
+//
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Single-element insert
+
+#include <iterator>
+#include <unordered_set>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_set<rvalstruct> Set;
+ Set s;
+ VERIFY( s.empty() );
+
+ std::pair<Set::iterator, bool> p = s.insert(rvalstruct(1));
+ VERIFY( p.second );
+ VERIFY( s.size() == 1 );
+ VERIFY( std::distance(s.begin(), s.end()) == 1 );
+ VERIFY( p.first == s.begin() );
+ VERIFY( (*p.first).val == 1 );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using __gnu_test::rvalstruct;
+
+ typedef std::unordered_set<rvalstruct> Set;
+ Set s;
+ VERIFY( s.empty() );
+
+ std::pair<Set::iterator, bool> p1 = s.insert(rvalstruct(2));
+ std::pair<Set::iterator, bool> p2 = s.insert(rvalstruct(2));
+ VERIFY( p1.second );
+ VERIFY( !p2.second );
+ VERIFY( s.size() == 1 );
+ VERIFY( p1.first == p2.first );
+ VERIFY( (*p1.first).val == 2 );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_rvalref.h b/libstdc++-v3/testsuite/util/testsuite_rvalref.h
index b44d6ddd12d..5610b77cc43 100644
--- a/libstdc++-v3/testsuite/util/testsuite_rvalref.h
+++ b/libstdc++-v3/testsuite/util/testsuite_rvalref.h
@@ -1,7 +1,8 @@
// -*- C++ -*-
// Testing utilities for the rvalue reference.
//
-// Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -27,35 +28,30 @@
namespace __gnu_test
{
- // This class is designed to test libstdc++'s template-based rvalue
- // reference support. It should fail at compile-time if there is an attempt
- // to copy it (although see note just below).
- class rvalstruct
+ // This class is designed to test libstdc++'s template-based rvalue
+ // reference support. It should fail at compile-time if there is an
+ // attempt to copy it.
+ struct rvalstruct
{
- bool
- operator=(const rvalstruct&);
-
- rvalstruct(const rvalstruct&);
-
- public:
int val;
bool valid;
- rvalstruct() : valid(false)
+ rvalstruct() : val(0), valid(true)
{ }
rvalstruct(int inval) : val(inval), valid(true)
{ }
-
+
rvalstruct&
operator=(int newval)
{
- VERIFY(valid == false);
- val = newval;
+ val = newval;
valid = true;
return *this;
}
+ rvalstruct(const rvalstruct&) = delete;
+
rvalstruct(rvalstruct&& in)
{
VERIFY(in.valid == true);
@@ -65,6 +61,9 @@ namespace __gnu_test
}
rvalstruct&
+ operator=(const rvalstruct&) = delete;
+
+ rvalstruct&
operator=(rvalstruct&& in)
{
VERIFY(in.valid == true);
@@ -75,11 +74,11 @@ namespace __gnu_test
}
};
- bool
+ inline bool
operator==(const rvalstruct& lhs, const rvalstruct& rhs)
{ return lhs.val == rhs.val; }
- bool
+ inline bool
operator<(const rvalstruct& lhs, const rvalstruct& rhs)
{ return lhs.val < rhs.val; }
@@ -156,15 +155,15 @@ namespace __gnu_test
int copycounter::copycount = 0;
- bool
+ inline bool
operator==(const copycounter& lhs, const copycounter& rhs)
{ return lhs.val == rhs.val; }
- bool
+ inline bool
operator<(const copycounter& lhs, const copycounter& rhs)
{ return lhs.val < rhs.val; }
- void
+ inline void
swap(copycounter& lhs, copycounter& rhs)
{
VERIFY(lhs.valid && rhs.valid);
@@ -175,4 +174,21 @@ namespace __gnu_test
} // namespace __gnu_test
+namespace std
+{
+ template<typename _Tp> struct hash;
+
+ /// std::hash specialization for type_index.
+ template<>
+ struct hash<__gnu_test::rvalstruct>
+ {
+ typedef size_t result_type;
+ typedef __gnu_test::rvalstruct argument_type;
+
+ size_t
+ operator()(const __gnu_test::rvalstruct& __rvs) const
+ { return __rvs.val; }
+ };
+}
+
#endif // _GLIBCXX_TESTSUITE_TR1_H