summaryrefslogtreecommitdiffstats
path: root/contrib/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc')
-rw-r--r--contrib/gcc/Makefile.in3342
-rw-r--r--contrib/gcc/builtins.c8566
-rw-r--r--contrib/gcc/c-common.c4527
-rw-r--r--contrib/gcc/c-common.h839
-rw-r--r--contrib/gcc/c-decl.c7153
-rw-r--r--contrib/gcc/c-lex.c492
-rw-r--r--contrib/gcc/c-opts.c606
-rw-r--r--contrib/gcc/c-tree.h578
-rw-r--r--contrib/gcc/c.opt322
-rw-r--r--contrib/gcc/config/i386/i386.md16165
-rw-r--r--contrib/gcc/config/i386/x-cygwin4
-rw-r--r--contrib/gcc/config/i386/x86-64.h34
-rw-r--r--contrib/gcc/config/x-linux2
-rwxr-xr-xcontrib/gcc/configure7211
-rw-r--r--contrib/gcc/cp/decl.c8221
-rw-r--r--contrib/gcc/cp/except.c382
-rw-r--r--contrib/gcc/cp/ptree.c64
-rw-r--r--contrib/gcc/dbxout.c2541
-rw-r--r--contrib/gcc/emit-rtl.c1812
-rw-r--r--contrib/gcc/final.c814
-rw-r--r--contrib/gcc/flags.h625
-rw-r--r--contrib/gcc/ginclude/stdarg.h4
-rw-r--r--contrib/gcc/ginclude/stddef.h21
-rw-r--r--contrib/gcc/libgcc2.c740
-rw-r--r--contrib/gcc/print-tree.c468
-rw-r--r--contrib/gcc/recog.c646
-rw-r--r--contrib/gcc/reload.c1977
-rw-r--r--contrib/gcc/toplev.c3926
28 files changed, 39719 insertions, 32363 deletions
diff --git a/contrib/gcc/Makefile.in b/contrib/gcc/Makefile.in
index 30815af..8c02cce 100644
--- a/contrib/gcc/Makefile.in
+++ b/contrib/gcc/Makefile.in
@@ -1,8 +1,9 @@
# Makefile for GNU Compiler Collection
# Run 'configure' to generate Makefile from Makefile.in
-# Copyright (C) 1987, 1988, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-# 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 1987, 1988, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+# 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
#This file is part of GCC.
@@ -18,8 +19,8 @@
#You should have received a copy of the GNU General Public License
#along with GCC; see the file COPYING. If not, write to
-#the Free Software Foundation, 59 Temple Place - Suite 330,
-#Boston MA 02111-1307, USA.
+#the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+#Boston MA 02110-1301, USA.
# The targets for external use include:
# all, doc, proto, install, install-cross, install-cross-rest,
@@ -71,18 +72,30 @@ program_transform_name := @program_transform_name@
# Directory where sources are, from where we are.
srcdir = @srcdir@
-docdir = @srcdir@/doc
+gcc_docdir = @srcdir@/doc
# Directory where sources are, absolute.
abs_srcdir = @abs_srcdir@
abs_docdir = @abs_srcdir@/doc
-# Top build directory, relative to here.
-top_builddir = ..
+# Top build directory for this package, relative to here.
+top_builddir = .
# objdir is set by configure.
# It's normally the absolute path to the current directory.
objdir = @objdir@
+host_subdir=@host_subdir@
+build_subdir=@build_subdir@
+build_libsubdir=@build_libsubdir@
+
+ifeq ($(host_subdir),.)
+build_objdir := ../$(build_subdir)
+build_libobjdir := ../$(build_libsubdir)
+else
+build_objdir := ../../$(build_subdir)
+build_libobjdir := ../../$(build_libsubdir)
+endif
+
# --------
# Defined vpaths
# --------
@@ -90,12 +103,12 @@ objdir = @objdir@
# Directory where sources are, from where we are.
VPATH = @srcdir@
-# We define a vpath for the sources of the .texi files here because they
+# We define a vpath for the sources of the .texi files here because they
# are split between multiple directories and we would rather use one implicit
# pattern rule for everything.
# This vpath could be extended within the Make-lang fragments.
-vpath %.texi $(docdir):$(docdir)/include
+vpath %.texi $(gcc_docdir):$(gcc_docdir)/include
# ----
# Default values for variables overridden in Makefile fragments.
@@ -117,10 +130,10 @@ T_ADAFLAGS =
# See below for how to change them for certain systems.
# List of language subdirectories.
-SUBDIRS =@subdirs@
+SUBDIRS =@subdirs@ build
# Selection of languages to be made.
-CONFIG_LANGUAGES = @all_languages@
+CONFIG_LANGUAGES = @all_selected_languages@
LANGUAGES = c gcov$(exeext) gcov-dump$(exeext) $(CONFIG_LANGUAGES)
# Selection of languages to be made during stage1 build.
@@ -132,14 +145,17 @@ BOOT_LANGUAGES = c @all_boot_languages@
# or BOOT_CFLAGS
# STAGE1_CFLAGS is set by configure on some targets or passed from toplevel
# and sets the CFLAGS passed to stage1 of a bootstrap compilation.
+# STAGE1_CHECKING enables checking for the stage1 compiler
# BOOT_CFLAGS is the value of CFLAGS to pass to the stage2, stage3 and stage4
# bootstrap compilations.
# XCFLAGS is used for most compilations but not when using the GCC just built.
# TCFLAGS is used for compilations with the GCC just built.
XCFLAGS =
TCFLAGS =
-CFLAGS = -g
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
STAGE1_CFLAGS = -g @stage1_cflags@
+STAGE1_CHECKING_CFLAGS = -DENABLE_CHECKING -DENABLE_ASSERT_CHECKING
BOOT_CFLAGS = -g -O2
# Flags to determine code coverage. When coverage is disabled, this will
@@ -159,10 +175,16 @@ coverageexts = .{gcda,gcno}
# STRICT_WARN and STRICT2_WARN are the additional warning flags to
# apply to the back end and the C front end, which may be compiled
# with other compilers. This is partially controlled by configure in
-# stage1, as not all versions of gcc understand -Wno-long-long.
+# stage1, as not all versions of gcc understand -Wno-long-long or
+# -Wno-variadic-macros.
+# CXX_COMPAT_WARN are C++ source compatibility warnings.
LOOSE_WARN = -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
STRICT_WARN = @strict1_warn@
-STRICT2_WARN = -pedantic -Wno-long-long -Wold-style-definition @WERROR@
+WERROR_FLAGS = @WERROR@
+STRICT2_WARN = -pedantic -Wno-long-long -Wno-variadic-macros \
+ -Wno-overlength-strings -Wold-style-definition -Wmissing-format-attribute \
+ $(WERROR_FLAGS)
+CXX_COMPAT_WARN = @cxx_compat_warn@
# This is set by --enable-checking. The idea is to catch forgotten
# "extern" tags in header files.
@@ -177,19 +199,23 @@ VALGRIND_DRIVER_DEFINES = @valgrind_path_defines@
# This is how we control whether or not the additional warnings are applied.
.-warn = $(STRICT_WARN)
+build-warn = $(STRICT_WARN)
GCC_WARN_CFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn)
-# These files are to have -Werror bypassed in stage2:
-# These are very hard to completely clean due to target complexities.
-gcc.o-warn = -Wno-error
-insn-conditions.o-warn = -Wno-error
+# These files are to have specific diagnostics suppressed, or are not to
+# be subject to -Werror:
# Bison-1.75 output often yields (harmless) -Wtraditional warnings
-gengtype-yacc.o-warn = -Wno-error
-c-parse.o-warn = -Wno-error
+build/gengtype-yacc.o-warn = -Wno-error
# flex output may yield harmless "no previous prototype" warnings
-gengtype-lex.o-warn = -Wno-error
+build/gengtype-lex.o-warn = -Wno-error
# SYSCALLS.c misses prototypes
SYSCALLS.c.X-warn = -Wno-strict-prototypes -Wno-error
+# These files need -Wno-error because the gimplifier triggers hard to fix
+# warnings when converting to GIMPLE form. The warnings are triggered because
+# moving the condition into the loop prevents the loop optimizer from
+# recognizing that the loop will always be executed at least once. We need
+# a new loop optimizer.
+reload1.o-warn = -Wno-error
# All warnings have to be shut off in stage1 if the compiler used then
# isn't gcc; configure determines that. WARN_CFLAGS will be either
@@ -211,9 +237,11 @@ BISON = @BISON@
BISONFLAGS =
FLEX = @FLEX@
FLEXFLAGS =
-AR = ar
+AR = @AR@
AR_FLAGS = rc
+NM = @NM@
RANLIB = @RANLIB@
+RANLIB_FLAGS = @ranlib_flags@
# -------------------------------------------
# Programs which operate on the build machine
@@ -240,6 +268,8 @@ INSTALL_SCRIPT = @INSTALL@
MAKEINFO = @MAKEINFO@
MAKEINFOFLAGS = --no-split
TEXI2DVI = texi2dvi
+TEXI2PDF = texi2pdf
+TEXI2HTML = $(MAKEINFO) --html
TEXI2POD = perl $(srcdir)/../contrib/texi2pod.pl
POD2MAN = pod2man --center="GNU" --release="gcc-$(version)"
# Some versions of `touch' (such as the version on Solaris 2.8)
@@ -251,6 +281,9 @@ STAMP = echo timestamp >
@SET_MAKE@
REMAKEFLAGS=LANGUAGES="$(LANGUAGES)" BOOT_CFLAGS="$(BOOT_CFLAGS)"
+# Locate mkinstalldirs.
+mkinstalldirs=$(SHELL) $(srcdir)/../mkinstalldirs
+
# --------
# UNSORTED
# --------
@@ -265,6 +298,18 @@ OUTPUT_OPTION = @OUTPUT_OPTION@
ZLIB = @zlibdir@ -lz
ZLIBINC = @zlibinc@
+# How to find GMP
+GMPLIBS = @GMPLIBS@
+GMPINC = @GMPINC@
+
+CPPLIB = ../libcpp/libcpp.a
+CPPINC = -I$(srcdir)/../libcpp/include
+
+# Where to find decNumber
+DECNUM = $(srcdir)/../libdecnumber
+DECNUMINC = -I$(DECNUM) -I../libdecnumber
+LIBDECNUMBER = ../libdecnumber/libdecnumber.a
+
# Substitution type for target's getgroups 2nd arg.
TARGET_GETGROUPS_T = @TARGET_GETGROUPS_T@
@@ -274,15 +319,17 @@ INSTALL_HEADERS_DIR = @build_install_headers_dir@
# Header files that are made available under the same name
# to programs compiled with GCC.
-USER_H = $(srcdir)/ginclude/float.h \
+USER_H = $(srcdir)/ginclude/decfloat.h \
+ $(srcdir)/ginclude/float.h \
$(srcdir)/ginclude/iso646.h \
$(srcdir)/ginclude/stdarg.h \
$(srcdir)/ginclude/stdbool.h \
$(srcdir)/ginclude/stddef.h \
$(srcdir)/ginclude/varargs.h \
- $(srcdir)/unwind.h \
$(EXTRA_HEADERS)
+UNWIND_H = $(srcdir)/unwind-generic.h
+
# The GCC to use for compiling libgcc.a and crt*.o.
# Usually the one we just built.
# Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS).
@@ -291,26 +338,28 @@ GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) ./xgcc -B./ -B$(build_tooldir)/bin/ -isyste
# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
# It omits XCFLAGS, and specifies -B./.
# It also specifies -isystem ./include to find, e.g., stddef.h.
-GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(LOOSE_WARN) -Wold-style-definition $($@-warn) -isystem ./include $(TCFLAGS)
+GCC_CFLAGS=$(CFLAGS_FOR_TARGET) $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(LOOSE_WARN) -Wold-style-definition $($@-warn) -isystem ./include $(TCFLAGS)
# ---------------------------------------------------
# Programs which produce files for the target machine
# ---------------------------------------------------
-AR_FOR_TARGET = ` \
+AR_FOR_TARGET := $(shell \
if [ -f $(objdir)/../binutils/ar ] ; then \
echo $(objdir)/../binutils/ar ; \
else \
if [ "$(host)" = "$(target)" ] ; then \
- echo ar; \
+ echo $(AR); \
else \
t='$(program_transform_name)'; echo ar | sed -e $$t ; \
fi; \
- fi`
+ fi)
AR_FLAGS_FOR_TARGET =
AR_CREATE_FOR_TARGET = $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) rc
AR_EXTRACT_FOR_TARGET = $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) x
-RANLIB_FOR_TARGET = ` \
+LIPO_FOR_TARGET = lipo
+ORIGINAL_AS_FOR_TARGET = @ORIGINAL_AS_FOR_TARGET@
+RANLIB_FOR_TARGET := $(shell \
if [ -f $(objdir)/../binutils/ranlib ] ; then \
echo $(objdir)/../binutils/ranlib ; \
else \
@@ -319,19 +368,20 @@ RANLIB_FOR_TARGET = ` \
else \
t='$(program_transform_name)'; echo ranlib | sed -e $$t ; \
fi; \
- fi`
-NM_FOR_TARGET = ` \
- if [ -f ./nm ] ; then \
- echo ./nm ; \
- elif [ -f $(objdir)/../binutils/nm-new ] ; then \
- echo $(objdir)/../binutils/nm-new ; \
+ fi)
+ORIGINAL_LD_FOR_TARGET = @ORIGINAL_LD_FOR_TARGET@
+ORIGINAL_NM_FOR_TARGET = @ORIGINAL_NM_FOR_TARGET@
+NM_FOR_TARGET = ./nm
+STRIP_FOR_TARGET := $(shell \
+ if [ -f $(objdir)/../binutils/strip ] ; then \
+ echo $(objdir)/../binutils/strip ; \
else \
if [ "$(host)" = "$(target)" ] ; then \
- echo nm; \
+ echo strip; \
else \
- t='$(program_transform_name)'; echo nm | sed -e $$t ; \
+ t='$(program_transform_name)'; echo strip | sed -e $$t ; \
fi; \
- fi`
+ fi)
# --------
# UNSORTED
@@ -343,6 +393,7 @@ OBSTACK_H = $(srcdir)/../include/obstack.h
SPLAY_TREE_H= $(srcdir)/../include/splay-tree.h
FIBHEAP_H = $(srcdir)/../include/fibheap.h
PARTITION_H = $(srcdir)/../include/partition.h
+MD5_H = $(srcdir)/../include/md5.h
# Default native SYSTEM_HEADER_DIR, to be overridden by targets.
NATIVE_SYSTEM_HEADER_DIR = /usr/include
@@ -350,7 +401,12 @@ NATIVE_SYSTEM_HEADER_DIR = /usr/include
CROSS_SYSTEM_HEADER_DIR = @CROSS_SYSTEM_HEADER_DIR@
# autoconf sets SYSTEM_HEADER_DIR to one of the above.
-SYSTEM_HEADER_DIR = @SYSTEM_HEADER_DIR@
+# Purge it of unneccessary internal relative paths
+# to directories that might not exist yet.
+# The sed idiom for this is to repeat the search-and-replace until it doesn't match, using :a ... ta.
+# Use single quotes here to avoid nested double- and backquotes, this
+# macro is also used in a double-quoted context.
+SYSTEM_HEADER_DIR = `echo @SYSTEM_HEADER_DIR@ | sed -e :a -e 's,[^/]*/\.\.\/,,' -e ta`
# Control whether to run fixproto and fixincludes.
STMP_FIXPROTO = @STMP_FIXPROTO@
@@ -391,12 +447,8 @@ GCC_THREAD_FILE=@thread_file@
OBJC_BOEHM_GC=@objc_boehm_gc@
GTHREAD_FLAGS=@gthread_flags@
extra_modes_file=@extra_modes_file@
+extra_opt_files=@extra_opt_files@
host_hook_obj=@out_host_hook_obj@
-# Be prepared for gcc2 merges.
-gcc_version=@gcc_version@
-gcc_version_trigger=@gcc_version_trigger@
-version=$(gcc_version)
-mainversion=`grep version_string $(srcdir)/version.c | sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/'`
# ------------------------
# Installation directories
@@ -463,6 +515,13 @@ man7dir = $(mandir)/man7
# Dir for temp files.
tmpdir = /tmp
+datarootdir = @datarootdir@
+docdir = @docdir@
+# Directory in which to build HTML
+build_htmldir = $(objdir)/HTML/gcc-$(version)
+# Directory in which to put HTML
+htmldir = @htmldir@
+
# Whether we were configured with NLS.
USE_NLS = @USE_NLS@
@@ -485,10 +544,20 @@ GGC_LIB=
LIBGCC = libgcc.a
INSTALL_LIBGCC = install-libgcc
+# "true" if the target C library headers are unavailable; "false"
+# otherwise.
+inhibit_libc = @inhibit_libc@
+ifeq ($(inhibit_libc),true)
+INHIBIT_LIBC_CFLAGS = -Dinhibit_libc
+endif
+
# Options to use when compiling libgcc2.a.
#
LIBGCC2_DEBUG_CFLAGS = -g
-LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED @inhibit_libc@
+LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) \
+ $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) \
+ -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED \
+ $(INHIBIT_LIBC_CFLAGS)
# Additional options to use when compiling libgcc2.a.
# Some targets override this to -isystem include
@@ -500,14 +569,15 @@ TARGET_LIBGCC2_CFLAGS =
# Options to use when compiling crtbegin/end.
CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline-functions -fno-exceptions \
- -fno-zero-initialized-in-bss -fno-unit-at-a-time
+ -fno-zero-initialized-in-bss -fno-toplevel-reorder \
+ $(INHIBIT_LIBC_CFLAGS)
# Additional sources to handle exceptions; overridden by targets as needed.
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
$(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
LIB2ADDEHSTATIC = $(LIB2ADDEH)
LIB2ADDEHSHARED = $(LIB2ADDEH)
-LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
+LIB2ADDEHDEP = $(UNWIND_H) unwind-pe.h unwind.inc unwind-dw2-fde.h unwind-dw2.h
# Don't build libunwind by default.
LIBUNWIND =
@@ -541,9 +611,10 @@ EXTRA_GCC_OBJS =@extra_gcc_objs@
# List of additional header files to install.
EXTRA_HEADERS =@extra_headers_list@
-# It is convenient for configure to add the assignment at the beginning,
-# so don't override it here.
-USE_COLLECT2 = collect2$(exeext)
+# The configure script will set this to collect2$(exeext), except on a
+# (non-Unix) host which can not build collect2, for which it will be
+# set to empty.
+COLLECT2 = @collect2@
# List of extra C and assembler files to add to static and shared libgcc2.
# Assembler files should have names ending in `.asm'.
@@ -553,9 +624,11 @@ LIB2FUNCS_EXTRA =
# Assembler files should have names ending in `.asm'.
LIB2FUNCS_STATIC_EXTRA =
-# List of extra C and assembler files to add to shared libgcc2.
-# Assembler files should have names ending in `.asm'.
-LIB2FUNCS_SHARED_EXTRA =
+# List of functions not to build from libgcc2.c.
+LIB2FUNCS_EXCLUDE =
+
+# Target sfp-machine.h file.
+SFP_MACHINE =
# Program to convert libraries.
LIBCONVERT =
@@ -586,20 +659,11 @@ GCC_PASSES=xgcc$(exeext) cc1$(exeext) specs $(EXTRA_PASSES)
# List of things which should already be built whenever we try to use xgcc
# to link anything.
-GCC_PARTS=$(GCC_PASSES) $(LIBGCC) $(EXTRA_PROGRAMS) $(USE_COLLECT2) $(EXTRA_PARTS)
+GCC_PARTS=$(GCC_PASSES) $(LIBGCC) $(EXTRA_PROGRAMS) $(COLLECT2) $(EXTRA_PARTS)
# Directory to link to, when using the target `maketest'.
DIR = ../gcc
-# Flags to use when cross-building GCC.
-# Prefix to apply to names of object files when using them
-# to run on the machine we are compiling on.
-BUILD_PREFIX = @BUILD_PREFIX@
-# Prefix to apply to names of object files when compiling them
-# to run on the machine we are compiling on.
-# The default for this variable is chosen to keep these rules
-# out of the way of the other rules for compiling the same source files.
-BUILD_PREFIX_1 = @BUILD_PREFIX_1@
# Native compiler for the build machine and its switches.
CC_FOR_BUILD = @CC_FOR_BUILD@
BUILD_CFLAGS= @BUILD_CFLAGS@ -DGENERATOR_FILE
@@ -661,40 +725,97 @@ CONFIG_H = config.h $(host_xm_file_list)
TCONFIG_H = tconfig.h $(xm_file_list)
TM_P_H = tm_p.h $(tm_p_file_list)
GTM_H = tm.h $(tm_file_list)
-TM_H = $(GTM_H) insn-constants.h insn-flags.h
-
-TARGET_H = $(TM_H) target.h
-HOOKS_H = hooks.h
+TM_H = $(GTM_H) insn-constants.h insn-flags.h options.h
+
+# Variables for version information.
+BASEVER := $(srcdir)/BASE-VER # 4.x.y
+DEVPHASE := $(srcdir)/DEV-PHASE # experimental, prerelease, ""
+DATESTAMP := $(srcdir)/DATESTAMP # YYYYMMDD or empty
+
+BASEVER_c := $(shell cat $(BASEVER))
+DEVPHASE_c := $(shell cat $(DEVPHASE))
+DATESTAMP_c := $(shell cat $(DATESTAMP))
+
+version := $(BASEVER_c)
+
+# For use in version.c - double quoted strings, with appropriate
+# surrounding punctuation and spaces, and with the datestamp and
+# development phase collapsed to the empty string in release mode
+# (i.e. if DEVPHASE_c is empty). The space immediately after the
+# comma in the $(if ...) constructs is significant - do not remove it.
+BASEVER_s := "\"$(BASEVER_c)\""
+DEVPHASE_s := "\"$(if $(DEVPHASE_c), ($(DEVPHASE_c)))\""
+DATESTAMP_s := "\"$(if $(DEVPHASE_c), $(DATESTAMP_c))\""
+
+# Shorthand variables for dependency lists.
+TARGET_H = $(TM_H) target.h insn-modes.h
+MACHMODE_H = machmode.h mode-classes.def insn-modes.h
+HOOKS_H = hooks.h $(MACHMODE_H)
+HOSTHOOKS_DEF_H = hosthooks-def.h $(HOOKS_H)
LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
TARGET_DEF_H = target-def.h $(HOOKS_H)
-MACHMODE_H = machmode.h mode-classes.def insn-modes.h
-RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H)
-RTL_H = $(RTL_BASE_H) genrtl.h input.h
+RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H) reg-notes.def insn-notes.def \
+ input.h $(REAL_H) statistics.h vec.h
+RTL_H = $(RTL_BASE_H) genrtl.h
PARAMS_H = params.h params.def
-TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def \
- input.h
+BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def
+TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h $(BUILTINS_DEF) \
+ input.h statistics.h vec.h treestruct.def $(HASHTAB_H)
BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h $(PARTITION_H) \
- hard-reg-set.h cfghooks.h
-COVERAGE_H = coverage.h gcov-io.h gcov-iov.h
+ hard-reg-set.h cfghooks.h $(OBSTACK_H)
+GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
+COVERAGE_H = coverage.h $(GCOV_IO_H)
DEMANGLE_H = $(srcdir)/../include/demangle.h
RECOG_H = recog.h
-EXPR_H = expr.h
+ALIAS_H = alias.h
+EMIT_RTL_H = emit-rtl.h
+FLAGS_H = flags.h options.h
+FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H)
+EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
OPTABS_H = optabs.h insn-codes.h
-REGS_H = regs.h varray.h $(MACHMODE_H)
-INTEGRATE_H = integrate.h varray.h
-LOOP_H = loop.h varray.h bitmap.h
+REGS_H = regs.h varray.h $(MACHMODE_H) $(OBSTACK_H) $(BASIC_BLOCK_H) $(FUNCTION_H)
+RESOURCE_H = resource.h hard-reg-set.h
+SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H)
+INTEGRATE_H = integrate.h $(VARRAY_H)
+CFGLAYOUT_H = cfglayout.h $(BASIC_BLOCK_H)
+CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H)
+IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
+IPA_REFERENCE_H = ipa-reference.h bitmap.h $(TREE_H)
+IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H)
+CGRAPH_H = cgraph.h $(TREE_H)
+DF_H = df.h bitmap.h $(BASIC_BLOCK_H) alloc-pool.h
+DDG_H = ddg.h sbitmap.h $(DF_H)
GCC_H = gcc.h version.h
GGC_H = ggc.h gtype-desc.h
TIMEVAR_H = timevar.h timevar.def
INSN_ATTR_H = insn-attr.h $(srcdir)/insn-addr.h $(srcdir)/varray.h
-C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H)
-C_TREE_H = c-tree.h $(C_COMMON_H)
-SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h
+C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H) $(GGC_H)
+C_PRAGMA_H = c-pragma.h $(CPPLIB_H)
+C_TREE_H = c-tree.h $(C_COMMON_H) toplev.h $(DIAGNOSTIC_H)
+SYSTEM_H = system.h hwint.h double-int.h $(srcdir)/../include/libiberty.h
PREDICT_H = predict.h predict.def
-CPPLIB_H = cpplib.h line-map.h
+CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
+ $(srcdir)/../libcpp/include/cpplib.h
+DECNUM_H = $(DECNUM)/decContext.h $(DECNUM)/decDPD.h $(DECNUM)/decNumber.h \
+ $(DECNUM)/decimal32.h $(DECNUM)/decimal64.h $(DECNUM)/decimal128.h
+MKDEPS_H = $(srcdir)/../libcpp/include/mkdeps.h
+SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h
+CPP_ID_DATA_H = $(CPPLIB_H) $(srcdir)/../libcpp/include/cpp-id-data.h
+TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H)
+TREE_GIMPLE_H = tree-gimple.h tree-iterator.h
+TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
+ bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h $(TREE_GIMPLE_H) \
+ $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H)
+TREE_SSA_LIVE_H = tree-ssa-live.h $(PARTITION_H) vecprim.h
PRETTY_PRINT_H = pretty-print.h input.h $(OBSTACK_H)
-DIAGNOSTIC_H = diagnostic.h diagnostic.def $(PRETTY_PRINT_H)
-C_PRETTY_PRINT_H = $(PRETTY_PRINT_H) $(C_COMMON_H) $(TREE_H)
+DIAGNOSTIC_H = diagnostic.h diagnostic.def $(PRETTY_PRINT_H) options.h
+C_PRETTY_PRINT_H = c-pretty-print.h $(PRETTY_PRINT_H) $(C_COMMON_H) $(TREE_H)
+SCEV_H = tree-scalar-evolution.h $(GGC_H) tree-chrec.h $(PARAMS_H)
+LAMBDA_H = lambda.h $(TREE_H) vec.h $(GGC_H)
+TREE_DATA_REF_H = tree-data-ref.h $(LAMBDA_H)
+VARRAY_H = varray.h $(MACHMODE_H) $(SYSTEM_H) coretypes.h $(TM_H)
+TREE_INLINE_H = tree-inline.h $(VARRAY_H) $(SPLAY_TREE_H)
+REAL_H = real.h $(MACHMODE_H)
#
# Now figure out from those variables how to compile and link.
@@ -709,16 +830,17 @@ INTERNAL_CFLAGS = -DIN_GCC @CROSS@
ALL_CFLAGS = $(X_CFLAGS) $(T_CFLAGS) \
$(CFLAGS) $(INTERNAL_CFLAGS) $(COVERAGE_FLAGS) $(WARN_CFLAGS) $(XCFLAGS) @DEFS@
-# Likewise.
-ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
+# Likewise. Put INCLUDES at the beginning: this way, if some autoconf macro
+# puts -I options in CPPFLAGS, our include files in the srcdir will always
+# win against random include files in /usr/include.
+ALL_CPPFLAGS = $(INCLUDES) $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
-# Build and host support libraries. FORBUILD is either
-# .. or ../$(build_alias) depending on whether host != build.
+# Build and host support libraries.
LIBIBERTY = ../libiberty/libiberty.a
-BUILD_LIBIBERTY = @FORBUILD@/libiberty/libiberty.a
+BUILD_LIBIBERTY = $(build_libobjdir)/libiberty/libiberty.a
# Dependencies on the intl and portability libraries.
-LIBDEPS= $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP)
+LIBDEPS= $(CPPLIB) $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP) $(LIBDECNUMBER)
# Likewise, for use in the tools that must run on this machine
# even if we are cross-building GCC.
@@ -726,7 +848,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
# How to link with both our special library facilities
# and the system's installed libraries.
-LIBS = @LIBS@ $(LIBIBERTY) $(LIBINTL) $(LIBICONV)
+LIBS = @LIBS@ $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBIBERTY) $(LIBDECNUMBER)
# Any system libraries needed just for GNAT.
SYSLIBS = @GNAT_LIBEXC@
@@ -738,14 +860,9 @@ LDEXP_LIB = @LDEXP_LIB@
# even if we are cross-building GCC.
BUILD_LIBS = $(BUILD_LIBIBERTY)
-BUILD_RTL = $(BUILD_PREFIX)rtl.o read-rtl.o $(BUILD_PREFIX)bitmap.o \
- $(BUILD_PREFIX)ggc-none.o min-insn-modes.o
-BUILD_SUPPORT = gensupport.o insn-conditions.o
-BUILD_EARLY_SUPPORT = gensupport.o dummy-conditions.o
-
-BUILD_PRINT = print-rtl1.o
-BUILD_ERRORS = $(BUILD_PREFIX)errors.o
-BUILD_VARRAY = $(BUILD_PREFIX)varray.o
+BUILD_RTL = build/rtl.o build/read-rtl.o build/ggc-none.o build/vec.o \
+ build/min-insn-modes.o build/gensupport.o build/print-rtl.o
+BUILD_ERRORS = build/errors.o
# Specify the directories to be searched for header files.
# Both . and srcdir are used, in that order,
@@ -755,10 +872,11 @@ BUILD_VARRAY = $(BUILD_PREFIX)varray.o
# currently being compiled, in both source trees, to be examined as well.
# libintl.h will be found in ../intl if we are using the included libintl.
INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
- -I$(srcdir)/../include @INCINTL@
+ -I$(srcdir)/../include @INCINTL@ \
+ $(CPPINC) $(GMPINC) $(DECNUMINC)
.c.o:
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
#
# Support for additional languages (other than C).
@@ -779,16 +897,16 @@ export AR_CREATE_FOR_TARGET
export AR_FLAGS_FOR_TARGET
export AR_EXTRACT_FOR_TARGET
export AWK
-export BUILD_PREFIX
-export BUILD_PREFIX_1
export DESTDIR
export GCC_FOR_TARGET
export INCLUDES
export INSTALL_DATA
export LIB1ASMSRC
export LIBGCC2_CFLAGS
+export LIPO_FOR_TARGET
export MACHMODE_H
export NM_FOR_TARGET
+export STRIP_FOR_TARGET
export RANLIB_FOR_TARGET
export libsubdir
export slibdir
@@ -833,84 +951,115 @@ SUBDIR_FLAGS_TO_PASS = $(ORDINARY_FLAGS_TO_PASS) \
#
# Lists of files for various purposes.
+# All option source files
+ALL_OPT_FILES=$(lang_opt_files) $(extra_opt_files)
+
# Target specific, C specific object file
C_TARGET_OBJS=@c_target_objs@
# Target specific, C++ specific object file
CXX_TARGET_OBJS=@cxx_target_objs@
+# Object files for gcc driver.
+GCC_OBJS = gcc.o opts-common.o gcc-options.o
+
# Language-specific object files for C and Objective C.
C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \
- c-objc-common.o c-dump.o c-pch.o libcpp.a $(C_TARGET_OBJS)
+ c-objc-common.o c-dump.o c-pch.o c-parser.o $(C_TARGET_OBJS) \
+ c-gimplify.o tree-mudflap.o c-pretty-print.o c-omp.o
# Language-specific object files for C.
-C_OBJS = c-parse.o c-lang.o c-pretty-print.o stub-objc.o $(C_AND_OBJC_OBJS)
+C_OBJS = c-lang.o stub-objc.o $(C_AND_OBJC_OBJS)
# Language-independent object files.
-
OBJS-common = \
+ double-int.o tree-chrec.o tree-scalar-evolution.o tree-data-ref.o \
+ tree-cfg.o tree-dfa.o tree-eh.o tree-ssa.o tree-optimize.o tree-gimple.o \
+ gimplify.o tree-pretty-print.o tree-into-ssa.o \
+ tree-outof-ssa.o tree-ssa-ccp.o tree-vn.o tree-ssa-uncprop.o \
+ tree-ssa-dce.o tree-ssa-copy.o tree-nrv.o tree-ssa-copyrename.o \
+ tree-ssa-pre.o tree-ssa-live.o tree-ssa-operands.o tree-ssa-alias.o \
+ tree-ssa-phiopt.o tree-ssa-forwprop.o tree-nested.o tree-ssa-dse.o \
+ tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o tree-iterator.o \
+ omp-low.o tree-phinodes.o tree-ssanames.o tree-sra.o tree-complex.o \
+ tree-vect-generic.o tree-ssa-loop.o tree-ssa-loop-niter.o \
+ tree-ssa-loop-manip.o tree-ssa-threadupdate.o tree-ssa-threadedge.o \
+ tree-vectorizer.o tree-vect-analyze.o tree-vect-transform.o \
+ tree-vect-patterns.o tree-ssa-loop-prefetch.o \
+ tree-ssa-loop-ivcanon.o tree-ssa-propagate.o tree-ssa-address.o \
+ tree-ssa-math-opts.o \
+ tree-ssa-loop-ivopts.o tree-if-conv.o tree-ssa-loop-unswitch.o \
alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \
cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \
- dbxout.o debug.o df.o diagnostic.o dojump.o doloop.o dominance.o \
- dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o \
+ dbxout.o ddg.o tree-ssa-loop-ch.o loop-invariant.o tree-ssa-loop-im.o \
+ debug.o df-core.o df-problems.o df-scan.o dfp.o diagnostic.o dojump.o \
+ dominance.o loop-doloop.o \
+ dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o \
expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \
genrtl.o ggc-common.o global.o graph.o gtype-desc.o \
haifa-sched.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o insn-modes.o \
insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o \
integrate.o intl.o jump.o langhooks.o lcm.o lists.o local-alloc.o \
- loop.o optabs.o options.o opts.o params.o postreload.o predict.o \
- print-rtl.o print-tree.o value-prof.o \
- profile.o ra.o ra-build.o ra-colorize.o ra-debug.o ra-rewrite.o \
+ mode-switching.o modulo-sched.o optabs.o options.o opts.o opts-common.o \
+ params.o postreload.o postreload-gcse.o predict.o \
+ insn-preds.o insn-automata.o pointer-set.o \
+ print-rtl.o print-tree.o profile.o value-prof.o var-tracking.o \
real.o recog.o reg-stack.o regclass.o regmove.o regrename.o \
reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o rtl-error.o \
sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o \
- sibcall.o simplify-rtx.o sreal.o stmt.o stor-layout.o stringpool.o \
- targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o unroll.o \
- varasm.o varray.o version.o vmsdbgout.o xcoffout.o alloc-pool.o \
- et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o
+ see.o simplify-rtx.o sreal.o stmt.o stor-layout.o stringpool.o \
+ struct-equiv.o targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
+ varasm.o varray.o vec.o version.o vmsdbgout.o xcoffout.o alloc-pool.o \
+ et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o passes.o \
+ tree-profile.o rtlhooks.o cfgexpand.o lambda-mat.o \
+ lambda-trans.o lambda-code.o tree-loop-linear.o tree-ssa-sink.o \
+ tree-vrp.o tree-stdarg.o tree-cfgcleanup.o tree-ssa-reassoc.o \
+ tree-ssa-structalias.o tree-object-size.o \
+ rtl-factoring.o
+
OBJS-md = $(out_object_file)
-OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) hashtable.o tree-inline.o \
- tree-optimize.o cgraph.o cgraphunit.o
+OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) tree-inline.o \
+ cgraph.o cgraphunit.o tree-nomudflap.o ipa.o ipa-inline.o \
+ ipa-utils.o ipa-reference.o ipa-pure-const.o ipa-type-escape.o \
+ ipa-prop.o ipa-cp.o
OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
OBJS-onestep = libbackend.o $(OBJS-archive)
-BACKEND = main.o libbackend.a
+BACKEND = main.o @TREEBROWSER@ libbackend.a $(CPPLIB) $(LIBDECNUMBER)
-# Files to be copied away after each stage in building.
-STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
+# Files to be copied after each stage in building.
+STAGECOPYSTUFF = insn-flags.h insn-config.h insn-codes.h \
insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \
- insn-attr.h insn-attrtab.c insn-opinit.c insn-constants.h tm-preds.h \
- tree-check.h insn-conditions.c min-insn-modes.c insn-modes.c insn-modes.h \
- s-flags s-config s-codes s-mlib s-genrtl s-modes s-gtype gtyp-gen.h \
- s-output s-recog s-emit s-extract s-peep s-check s-conditions \
- s-attr s-attrtab s-opinit s-preds s-constants s-crt0 \
- genemit$(build_exeext) genoutput$(build_exeext) genrecog$(build_exeext) \
- genextract$(build_exeext) genflags$(build_exeext) gencodes$(build_exeext) \
- genconfig$(build_exeext) genpeep$(build_exeext) genattrtab$(build_exeext) \
- genattr$(build_exeext) genopinit$(build_exeext) gengenrtl$(build_exeext) \
- gencheck$(build_exeext) genpreds$(build_exeext) genconstants$(build_exeext) \
- gengtype$(build_exeext) genconditions$(build_exeext) genmodes$(build_exeext) \
- genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c \
- xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \
+ insn-attr.h insn-attrtab.c insn-opinit.c insn-preds.c insn-constants.h \
+ tm-preds.h tm-constrs.h \
+ tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
+ genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-gen.h
+
+# Files to be moved away after each stage in building.
+STAGEMOVESTUFF = *$(objext) s-* \
+ xgcc$(exeext) cpp$(exeext) cc1$(exeext) cc1*-dummy$(exeext) $(EXTRA_PASSES) \
$(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
protoize$(exeext) unprotoize$(exeext) \
- $(SPECS) collect2$(exeext) $(USE_COLLECT2) \
+ $(SPECS) collect2$(exeext) \
gcov-iov$(build_exeext) gcov$(exeext) gcov-dump$(exeext) \
- *.[0-9][0-9].* *.[si] libcpp.a libbackend.a libgcc.mk \
+ *.[0-9][0-9].* *.[si] *-checksum.c libbackend.a libgcc.mk \
$(LANG_STAGESTUFF)
# Defined in libgcc2.c, included only in the static library.
LIB2FUNCS_ST = _eprintf __gcc_bcmp
# Defined in libgcov.c, included only in gcov library
-LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta
+LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
+ _gcov_fork _gcov_execl _gcov_execlp _gcov_execle \
+ _gcov_execv _gcov_execvp _gcov_execve \
+ _gcov_interval_profiler _gcov_pow2_profiler _gcov_one_value_profiler
FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
_fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
@@ -927,6 +1076,29 @@ TPBIT_FUNCS = _pack_tf _unpack_tf _addsub_tf _mul_tf _div_tf \
_lt_tf _le_tf _unord_tf _si_to_tf _tf_to_si _negate_tf _make_tf \
_tf_to_df _tf_to_sf _thenan_tf _tf_to_usi _usi_to_tf
+D32PBIT_FUNCS = _addsub_sd _div_sd _mul_sd _plus_sd _minus_sd \
+ _eq_sd _ne_sd _lt_sd _gt_sd _le_sd _ge_sd \
+ _sd_to_si _sd_to_di _sd_to_usi _sd_to_udi \
+ _si_to_sd _di_to_sd _usi_to_sd _udi_to_sd \
+ _sd_to_sf _sd_to_df _sd_to_xf _sf_to_sd _df_to_sd _xf_to_sd \
+ _sd_to_dd _sd_to_td _unord_sd _conv_sd
+
+D64PBIT_FUNCS = _addsub_dd _div_dd _mul_dd _plus_dd _minus_dd \
+ _eq_dd _ne_dd _lt_dd _gt_dd _le_dd _ge_dd \
+ _dd_to_si _dd_to_di _dd_to_usi _dd_to_udi \
+ _si_to_dd _di_to_dd _usi_to_dd _udi_to_dd \
+ _dd_to_sf _dd_to_df _dd_to_xf \
+ _sf_to_dd _df_to_dd _xf_to_dd \
+ _dd_to_sd _dd_to_td _unord_dd _conv_dd
+
+D128PBIT_FUNCS = _addsub_td _div_td _mul_td _plus_td _minus_td \
+ _eq_td _ne_td _lt_td _gt_td _le_td _ge_td \
+ _td_to_si _td_to_di _td_to_usi _td_to_udi \
+ _si_to_td _di_to_td _usi_to_td _udi_to_td \
+ _td_to_sf _td_to_df _td_to_xf \
+ _sf_to_td _df_to_td _xf_to_td \
+ _td_to_sd _td_to_dd _unord_td _conv_td
+
# These might cause a divide overflow trap and so are compiled with
# unwinder info.
LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4
@@ -937,7 +1109,7 @@ LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4
# The following targets define the interface between us and the languages.
#
# all.cross, start.encap, rest.encap,
-# install-normal, install-common, install-info, install-man,
+# install-common, install-info, install-man,
# uninstall,
# mostlyclean, clean, distclean, maintainer-clean,
# stage1, stage2, stage3, stage4
@@ -950,9 +1122,6 @@ LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4
# language hooks, generated by configure
@language_hooks@
-# Set up library path if needed.
-@set_gcc_lib_path@
-
# per-language makefile fragments
ifneq ($(LANG_MAKEFRAGS),)
include $(LANG_MAKEFRAGS)
@@ -977,7 +1146,43 @@ endif
# Rebuilding this configuration
# -----------------------------
-Makefile: config.status $(srcdir)/Makefile.in $(srcdir)/version.c $(LANG_MAKEFRAGS)
+# On the use of stamps:
+# Consider the example of tree-check.h. It is constructed with build/gencheck.
+# A simple rule to build tree-check.h would be
+# tree-check.h: build/gencheck$(build_exeext)
+# $(RUN_GEN) build/gencheck$(build_exeext) > tree-check.h
+#
+# but tree-check.h doesn't change every time gencheck changes. It would the
+# nice if targets that depend on tree-check.h wouldn't be rebuild
+# unnecessarily when tree-check.h is unchanged. To make this, tree-check.h
+# must not be overwritten with a identical copy. One solution is to use a
+# temporary file
+# tree-check.h: build/gencheck$(build_exeext)
+# $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h
+# $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
+#
+# This solution has a different problem. Since the time stamp of tree-check.h
+# is unchanged, make will try to update tree-check.h every time it runs.
+# To prevent this, one can add a stamp
+# tree-check.h: s-check
+# s-check : build/gencheck$(build_exeext)
+# $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h
+# $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
+# $(STAMP) s-check
+#
+# The problem with this solution is that make thinks that tree-check.h is
+# always unchanged. Make must be deceived into thinking that tree-check.h is
+# rebuild by the "tree-check.h: s-check" rule. To do this, add a dummy command:
+# tree-check.h: s-check; @true
+# s-check : build/gencheck$(build_exeext)
+# $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h
+# $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
+# $(STAMP) s-check
+#
+# This is what is done in this makefile. Note that mkconfig.sh has a
+# move-if-change built-in
+
+Makefile: config.status $(srcdir)/Makefile.in $(LANG_MAKEFRAGS)
LANGUAGES="$(CONFIG_LANGUAGES)" \
CONFIG_HEADERS= \
CONFIG_SHELL="$(SHELL)" \
@@ -1001,7 +1206,7 @@ cs-bconfig.h: Makefile
cs-tconfig.h: Makefile
TARGET_CPU_DEFAULT="" \
- HEADERS="$(xm_include_list)" DEFINES="$(xm_defines)" \
+ HEADERS="$(xm_include_list)" DEFINES="USED_FOR_TARGET $(xm_defines)" \
$(SHELL) $(srcdir)/mkconfig.sh tconfig.h
cs-tm.h: Makefile
@@ -1019,7 +1224,8 @@ cs-tm_p.h: Makefile
# might be on a read-only file system. If configured for maintainer mode
# then do allow autoconf to be run.
-$(srcdir)/configure: @MAINT@ $(srcdir)/configure.ac
+$(srcdir)/configure: @MAINT@ $(srcdir)/configure.ac $(srcdir)/aclocal.m4 \
+ $(srcdir)/acinclude.m4
(cd $(srcdir) && autoconf)
gccbug: $(srcdir)/gccbug.in
@@ -1028,9 +1234,6 @@ gccbug: $(srcdir)/gccbug.in
mklibgcc: $(srcdir)/mklibgcc.in
CONFIG_FILES=mklibgcc CONFIG_HEADERS= ./config.status
-mkheaders: $(srcdir)/mkheaders.in
- CONFIG_FILES=mkheaders CONFIG_HEADERS= ./config.status
-
# cstamp-h.in controls rebuilding of config.in.
# It is named cstamp-h.in and not stamp-h.in so the mostlyclean rule doesn't
# delete it. A stamp file is needed as autoheader won't update the file if
@@ -1057,7 +1260,7 @@ cstamp-h: config.in config.status
# Really, really stupid make features, such as SUN's KEEP_STATE, may force
# a target to build even if it is up-to-date. So we must verify that
# config.status does not exist before failing.
-config.status: $(srcdir)/configure $(srcdir)/config.gcc version.c
+config.status: $(srcdir)/configure $(srcdir)/config.gcc
@if [ ! -f config.status ] ; then \
echo You must configure gcc. Look at http://gcc.gnu.org/install/ for details.; \
false; \
@@ -1071,8 +1274,8 @@ config.status: $(srcdir)/configure $(srcdir)/config.gcc version.c
all.internal: start.encap rest.encap doc
# This is what to compile if making a cross-compiler.
-all.cross: native gcc-cross cpp$(exeext) specs \
- $(LIBGCC) $(EXTRA_PARTS) lang.all.cross doc
+all.cross: native gcc-cross$(exeext) cpp$(exeext) specs \
+ $(LIBGCC) $(EXTRA_PARTS) lang.all.cross doc @GENINSRC@ srcextra
# This is what must be made before installing GCC and converting libraries.
start.encap: native xgcc$(exeext) cpp$(exeext) specs \
xlimits.h lang.start.encap @GENINSRC@ srcextra
@@ -1081,14 +1284,13 @@ rest.encap: $(STMP_FIXPROTO) $(LIBGCC) $(EXTRA_PARTS) lang.rest.encap
# This is what is made with the host's compiler
# whether making a cross compiler or not.
native: config.status auto-host.h build-@POSUB@ $(LANGUAGES) \
- $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2)
+ $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2)
# Define the names for selecting languages in LANGUAGES.
-C c: cc1$(exeext)
-PROTO: proto
+c: cc1$(exeext)
# Tell GNU make these are phony targets.
-.PHONY: C c PROTO proto
+.PHONY: c proto
# On the target machine, finish building a cross compiler.
# This does the things that can't be done on the host machine.
@@ -1098,27 +1300,81 @@ rest.cross: $(LIBGCC) specs
# This is used only if the user explicitly asks for it.
compilations: $(BACKEND)
-# Like libcpp.a, this archive is strictly for the host.
+# This archive is strictly for the host.
libbackend.a: $(OBJS@onestep@)
-rm -rf libbackend.a
$(AR) $(AR_FLAGS) libbackend.a $(OBJS@onestep@)
- -$(RANLIB) libbackend.a
+ -$(RANLIB) $(RANLIB_FLAGS) libbackend.a
# We call this executable `xgcc' rather than `gcc'
# to avoid confusion if the current directory is in the path
# and CC is `gcc'. It is renamed to `gcc' when it is installed.
-xgcc$(exeext): gcc.o gccspec.o version.o intl.o prefix.o \
+xgcc$(exeext): $(GCC_OBJS) gccspec.o version.o intl.o prefix.o \
version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o gccspec.o intl.o \
- prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) gccspec.o \
+ intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
# cpp is to cpp0 as gcc is to cc1.
# The only difference from xgcc is that it's linked with cppspec.o
# instead of gccspec.o.
-cpp$(exeext): gcc.o cppspec.o version.o intl.o prefix.o \
+cpp$(exeext): $(GCC_OBJS) cppspec.o version.o intl.o prefix.o \
version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o cppspec.o intl.o \
- prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) cppspec.o \
+ intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
+
+# Create links to binutils, especially for in-tree builds, to make -B.
+# use them. We need hard links so that directories can be shuffled
+# during toplevel bootstrap.
+# Go through an additional indirection, because the file we create
+# can be either `sometool' (if it is a script) or `sometool$(exeext)'
+# (if it is a hard link).
+stamp-as: $(ORIGINAL_AS_FOR_TARGET)
+ @echo creating as; \
+ case "$(ORIGINAL_AS_FOR_TARGET)" in \
+ ./as) ;; \
+ ../*) \
+ rm -f as$(exeext); \
+ echo $(LN) $< as$(exeext); \
+ $(LN) $< as$(exeext) || cp $< as$(exeext) ;; \
+ *) \
+ rm -f as; \
+ echo '#!$(SHELL)' > as; \
+ echo 'exec $(ORIGINAL_AS_FOR_TARGET) "$$@"' >> as ; \
+ chmod +x as ;; \
+ esac
+ echo timestamp > $@
+
+stamp-collect-ld: $(ORIGINAL_LD_FOR_TARGET)
+ @echo creating collect-ld; \
+ case "$(ORIGINAL_LD_FOR_TARGET)" in \
+ ./collect-ld) ;; \
+ ../*) \
+ rm -f collect-ld$(exeext); \
+ echo $(LN) $< collect-ld$(exeext); \
+ $(LN) $< collect-ld$(exeext) || cp $< collect-ld$(exeext) ;; \
+ *) \
+ rm -f collect-ld$(exeext); \
+ echo '#!$(SHELL)' > collect-ld; \
+ echo 'exec $(ORIGINAL_LD_FOR_TARGET) "$$@"' >> collect-ld ; \
+ chmod +x collect-ld ;; \
+ esac
+ echo timestamp > $@
+
+stamp-nm: $(ORIGINAL_NM_FOR_TARGET)
+ @echo creating nm; \
+ case "$(ORIGINAL_NM_FOR_TARGET)" in \
+ ./nm) ;; \
+ ../*) \
+ rm -f nm$(exeext); \
+ echo $(LN) $< nm$(exeext); \
+ $(LN) $< nm$(exeext) || cp $< nm$(exeext) ;; \
+ *) \
+ rm -f nm$(exeext); \
+ echo '#!$(SHELL)' > nm; \
+ echo 'exec $(ORIGINAL_NM_FOR_TARGET) "$$@"' >> nm ; \
+ chmod +x nm ;; \
+ esac
+ echo timestamp > $@
# Dump a specs file to make -B./ read these specs over installed ones.
$(SPECS): xgcc$(exeext)
@@ -1128,12 +1384,23 @@ $(SPECS): xgcc$(exeext)
# We do want to create an executable named `xgcc', so we can use it to
# compile libgcc2.a.
# Also create gcc-cross, so that install-common will install properly.
-gcc-cross: xgcc$(exeext)
+gcc-cross$(exeext): xgcc$(exeext)
cp xgcc$(exeext) gcc-cross$(exeext)
-cc1$(exeext): $(C_OBJS) $(BACKEND) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cc1$(exeext) \
- $(C_OBJS) $(BACKEND) $(LIBS)
+dummy-checksum.o : dummy-checksum.c
+
+cc1-dummy$(exeext): $(C_OBJS) dummy-checksum.o $(BACKEND) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) dummy-checksum.o \
+ $(BACKEND) $(LIBS)
+
+cc1-checksum.c : cc1-dummy$(exeext) build/genchecksum$(build_exeext)
+ build/genchecksum$(build_exeext) cc1-dummy$(exeext) > $@
+
+cc1-checksum.o : cc1-checksum.c
+
+cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) cc1-checksum.o \
+ $(BACKEND) $(LIBS)
# Build the version of limits.h that we will install.
xlimits.h: glimits.h limitx.h limity.h
@@ -1148,21 +1415,21 @@ xlimits.h: glimits.h limitx.h limity.h
LIB2ADD = $(LIB2FUNCS_EXTRA)
LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
-LIB2ADD_SH = $(LIB2FUNCS_SHARED_EXTRA)
-libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) $(LIB2ADD_SH) \
- xgcc$(exeext) specs
+libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) specs \
+ xgcc$(exeext) stamp-as stamp-collect-ld stamp-nm
objext='$(objext)' \
LIB1ASMFUNCS='$(LIB1ASMFUNCS)' \
LIB2FUNCS_ST='$(LIB2FUNCS_ST)' \
+ LIB2FUNCS_EXCLUDE='$(LIB2FUNCS_EXCLUDE)' \
LIBGCOV='$(LIBGCOV)' \
LIB2ADD='$(LIB2ADD)' \
LIB2ADD_ST='$(LIB2ADD_ST)' \
- LIB2ADD_SH='$(LIB2ADD_SH)' \
LIB2ADDEH='$(LIB2ADDEH)' \
LIB2ADDEHSTATIC='$(LIB2ADDEHSTATIC)' \
LIB2ADDEHSHARED='$(LIB2ADDEHSHARED)' \
LIB2ADDEHDEP='$(LIB2ADDEHDEP)' \
+ LIB2_SIDITI_CONV_FUNCS='$(LIB2_SIDITI_CONV_FUNCS)' \
LIBUNWIND='$(LIBUNWIND)' \
LIBUNWINDDEP='$(LIBUNWINDDEP)' \
SHLIBUNWIND_LINK='$(SHLIBUNWIND_LINK)' \
@@ -1174,6 +1441,14 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) $(LIB2ADD_SH
DPBIT_FUNCS='$(DPBIT_FUNCS)' \
TPBIT='$(TPBIT)' \
TPBIT_FUNCS='$(TPBIT_FUNCS)' \
+ DFP_ENABLE='$(DFP_ENABLE)' \
+ DFP_CFLAGS='$(DFP_CFLAGS)' \
+ D32PBIT='$(D32PBIT)' \
+ D32PBIT_FUNCS='$(D32PBIT_FUNCS)' \
+ D64PBIT='$(D64PBIT)' \
+ D64PBIT_FUNCS='$(D64PBIT_FUNCS)' \
+ D128PBIT='$(D128PBIT)' \
+ D128PBIT_FUNCS='$(D128PBIT_FUNCS)' \
MULTILIBS=`$(GCC_FOR_TARGET) --print-multi-lib` \
EXTRA_MULTILIB_PARTS='$(EXTRA_MULTILIB_PARTS)' \
SHLIB_LINK='$(SHLIB_LINK)' \
@@ -1185,18 +1460,21 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) $(LIB2ADD_SH
SHLIB_MAPFILES='$(SHLIB_MAPFILES)' \
SHLIB_NM_FLAGS='$(SHLIB_NM_FLAGS)' \
MULTILIB_OSDIRNAMES='$(MULTILIB_OSDIRNAMES)' \
- mkinstalldirs='$(SHELL) $(srcdir)/mkinstalldirs' \
+ ASM_HIDDEN_OP='$(ASM_HIDDEN_OP)' \
+ GCC_FOR_TARGET='$(GCC_FOR_TARGET)' \
+ mkinstalldirs='$(mkinstalldirs)' \
$(SHELL) mklibgcc > tmp-libgcc.mk
mv tmp-libgcc.mk libgcc.mk
# All the things that might cause us to want to recompile bits of libgcc.
-LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
+LIBGCC_DEPS = $(GCC_PASSES) stmp-int-hdrs $(STMP_FIXPROTO) \
libgcc.mk $(srcdir)/libgcc2.c $(srcdir)/libgcov.c $(TCONFIG_H) \
- $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \
+ $(MACHMODE_H) longlong.h gbl-ctors.h config.status $(srcdir)/libgcc2.h \
tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
- $(LIB2ADD_ST) $(LIB2ADD_SH) $(LIB2ADDEH) $(LIB2ADDEHDEP) \
- $(EXTRA_PARTS) $(srcdir)/config/$(LIB1ASMSRC) \
- $(srcdir)/gcov-io.h $(srcdir)/gcov-io.c gcov-iov.h
+ config/dfp-bit.h config/dfp-bit.c \
+ $(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
+ $(srcdir)/config/$(LIB1ASMSRC) \
+ $(srcdir)/gcov-io.h $(srcdir)/gcov-io.c gcov-iov.h $(SFP_MACHINE)
libgcov.a: libgcc.a; @true
@@ -1229,7 +1507,7 @@ s-mlib: $(srcdir)/genmultilib Makefile
$(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' no \
> tmp-mlib.h; \
fi
- $(SHELL) $(srcdir)/move-if-change tmp-mlib.h multilib.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-mlib.h multilib.h
$(STAMP) s-mlib
# Build multiple copies of libgcc.a, one for each target switch.
@@ -1247,33 +1525,33 @@ stmp-multilib: $(LIBGCC_DEPS)
$(T)crtbegin.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
- @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_BEGIN \
+ -c $(srcdir)/crtstuff.c -DCRT_BEGIN \
-o $(T)crtbegin$(objext)
$(T)crtend.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
- @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_END \
+ -c $(srcdir)/crtstuff.c -DCRT_END \
-o $(T)crtend$(objext)
# These are versions of crtbegin and crtend for shared libraries.
$(T)crtbeginS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS_S) \
- @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFS_O \
+ -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFS_O \
-o $(T)crtbeginS$(objext)
$(T)crtendS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS_S) \
- @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_END -DCRTSTUFFS_O \
+ -c $(srcdir)/crtstuff.c -DCRT_END -DCRTSTUFFS_O \
-o $(T)crtendS$(objext)
# This is a version of crtbegin for -static links.
$(T)crtbeginT.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
- @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O \
+ -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O \
-o $(T)crtbeginT$(objext)
# Compile the start modules crt0.o and mcrt0.o that are linked with
@@ -1296,60 +1574,62 @@ s-crt0: $(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H)
# C language specific files.
c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) flags.h $(DIAGNOSTIC_H) $(TM_P_H)
-c-parse.o : c-parse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(GGC_H) intl.h $(C_TREE_H) input.h flags.h toplev.h output.h $(CPPLIB_H) \
- varray.h gt-c-parse.h
+ $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TM_P_H)
+c-parser.o : c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(GGC_H) $(TIMEVAR_H) $(C_TREE_H) input.h $(FLAGS_H) toplev.h output.h \
+ $(CPPLIB_H) gt-c-parser.h langhooks.h $(C_COMMON_H) $(C_PRAGMA_H) \
+ vec.h $(TARGET_H)
srcextra: gcc.srcextra lang.srcextra
-gcc.srcextra: c-parse.y c-parse.c gengtype-lex.c gengtype-yacc.c gengtype-yacc.h
+gcc.srcextra: gengtype-lex.c gengtype-yacc.c gengtype-yacc.h
-cp -p $^ $(srcdir)
-c-parse.c: c-parse.y
- -$(BISON) $(BISONFLAGS) -o $@ $<
-
-c-parse.y: c-parse.in
- echo '/*WARNING: This file is automatically generated!*/' >tmp-c-parse.y
- sed -e "/^@@ifobjc.*/,/^@@end_ifobjc.*/d" \
- -e "/^@@ifc.*/d" -e "/^@@end_ifc.*/d" $< >>tmp-c-parse.y
- $(SHELL) $(srcdir)/move-if-change tmp-c-parse.y $@
-
c-incpath.o: c-incpath.c c-incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \
- intl.h prefix.h coretypes.h $(TM_H) cppdefault.h
+ intl.h prefix.h coretypes.h $(TM_H) cppdefault.h $(TARGET_H) \
+ $(MACHMODE_H)
c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) $(C_TREE_H) $(GGC_H) $(TARGET_H) flags.h function.h output.h \
- $(EXPR_H) debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) \
- opts.h c-pragma.h gt-c-decl.h cgraph.h $(HASHTAB_H) libfuncs.h except.h \
- $(LANGHOOKS_DEF_H)
-c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \
- $(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H)
+ $(RTL_H) $(C_TREE_H) $(GGC_H) $(TARGET_H) $(FLAGS_H) $(FUNCTION_H) output.h \
+ $(EXPR_H) debug.h toplev.h intl.h $(TM_P_H) $(TREE_INLINE_H) $(TIMEVAR_H) \
+ opts.h $(C_PRAGMA_H) gt-c-decl.h $(CGRAPH_H) $(HASHTAB_H) libfuncs.h \
+ except.h $(LANGHOOKS_DEF_H) $(TREE_DUMP_H) $(C_COMMON_H) $(CPPLIB_H) \
+ $(DIAGNOSTIC_H) input.h langhooks.h $(TREE_GIMPLE_H) tree-mudflap.h \
+ pointer-set.h
+c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h output.h $(EXPR_H) \
+ $(RTL_H) toplev.h $(TM_P_H) langhooks.h $(GGC_H) $(TREE_FLOW_H) \
+ $(TREE_GIMPLE_H) tree-iterator.h
c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) $(C_PRETTY_PRINT_H) $(DIAGNOSTIC_H) \
- $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-c.h
+ $(C_TREE_H) $(DIAGNOSTIC_H) \
+ $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-c.h \
+ c-objc-common.h $(C_PRAGMA_H) c-common.def $(TREE_INLINE_H)
stub-objc.o : stub-objc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
- $(GGC_H) $(C_COMMON_H)
+ $(C_COMMON_H)
c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) debug.h $(C_TREE_H) $(C_COMMON_H) real.h c-incpath.h cppdefault.h \
- c-pragma.h input.h intl.h flags.h toplev.h output.h \
- $(CPPLIB_H) $(EXPR_H) $(TM_P_H)
+ $(RTL_H) debug.h $(C_TREE_H) $(C_COMMON_H) $(REAL_H) $(SPLAY_TREE_H) \
+ $(C_PRAGMA_H) input.h intl.h $(FLAGS_H) toplev.h output.h \
+ $(CPPLIB_H) $(TIMEVAR_H) $(TM_P_H)
c-ppoutput.o : c-ppoutput.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(C_COMMON_H) $(TREE_H) $(CPPLIB_H) cpphash.h $(TM_P_H) c-pragma.h
-c-objc-common.o : c-objc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) $(EXPR_H) $(C_TREE_H) \
- flags.h toplev.h tree-inline.h $(DIAGNOSTIC_H) $(VARRAY_H) \
- langhooks.h $(GGC_H) $(TARGET_H) cgraph.h
+ $(C_COMMON_H) $(TREE_H) $(CPPLIB_H) $(srcdir)/../libcpp/internal.h \
+ $(C_PRAGMA_H)
+c-objc-common.o : c-objc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(TREE_H) $(C_TREE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) \
+ $(FUNCTION_H) $(FLAGS_H) toplev.h $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(VARRAY_H) \
+ langhooks.h $(GGC_H) $(TARGET_H) $(C_PRETTY_PRINT_H) c-objc-common.h \
+ tree-mudflap.h
c-aux-info.o : c-aux-info.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) flags.h toplev.h
-c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- flags.h toplev.h $(C_COMMON_H) real.h
-c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- function.h c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) gt-c-pragma.h
-graph.o: graph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h flags.h output.h \
- $(RTL_H) function.h hard-reg-set.h $(BASIC_BLOCK_H) graph.h
-sbitmap.o: sbitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- hard-reg-set.h $(BASIC_BLOCK_H)
+ $(C_TREE_H) $(FLAGS_H) toplev.h
+c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(FLAGS_H) toplev.h $(C_COMMON_H) convert.h $(C_TREE_H) \
+ langhooks.h $(TARGET_H)
+c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FUNCTION_H) $(C_PRAGMA_H) toplev.h output.h $(GGC_H) $(TM_P_H) \
+ $(C_COMMON_H) $(TARGET_H) gt-c-pragma.h $(CPPLIB_H) $(FLAGS_H)
+graph.o: graph.c $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(FLAGS_H) output.h \
+ $(RTL_H) $(FUNCTION_H) hard-reg-set.h $(BASIC_BLOCK_H) graph.h $(OBSTACK_H)
+sbitmap.o: sbitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) hard-reg-set.h $(BASIC_BLOCK_H) $(OBSTACK_H)
COLLECT2_OBJS = collect2.o tlink.o intl.o version.o
COLLECT2_LIBS = @COLLECT2_LIBS@
@@ -1359,9 +1639,9 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
$(COLLECT2_OBJS) $(LIBS) $(COLLECT2_LIBS)
mv -f T$@ $@
-collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) gstab.h intl.h \
+collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h \
$(OBSTACK_H) $(DEMANGLE_H) collect2.h version.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_MACHINE=\"$(target_noncanonical)\" \
-c $(srcdir)/collect2.c $(OUTPUT_OPTION)
@@ -1371,46 +1651,56 @@ tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h
# A file used by all variants of C.
c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(OBSTACK_H) $(C_COMMON_H) flags.h toplev.h output.h c-pragma.h intl.h \
+ $(OBSTACK_H) $(C_COMMON_H) $(FLAGS_H) toplev.h output.h $(C_PRAGMA_H) \
$(GGC_H) $(EXPR_H) $(TM_P_H) builtin-types.def builtin-attrs.def \
- $(DIAGNOSTIC_H) gt-c-common.h langhooks.h varray.h $(RTL_H) \
- $(TARGET_H) $(C_TREE_H)
-c-pretty-print.o : c-pretty-print.c $(C_PRETTY_PRINT_H) \
- $(C_COMMON_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) real.h
+ $(DIAGNOSTIC_H) gt-c-common.h langhooks.h $(VARRAY_H) $(RTL_H) \
+ $(TARGET_H) $(C_TREE_H) tree-iterator.h langhooks.h tree-mudflap.h \
+ intl.h opts.h $(REAL_H) $(CPPLIB_H) $(TREE_INLINE_H) $(HASHTAB_H) \
+ $(BUILTINS_DEF)
-c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- c-pragma.h flags.h toplev.h langhooks.h tree-inline.h $(DIAGNOSTIC_H) \
- intl.h debug.h $(C_COMMON_H) opts.h options.h $(PARAMS_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+c-pretty-print.o : c-pretty-print.c $(C_PRETTY_PRINT_H) \
+ $(C_TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(REAL_H) \
+ $(DIAGNOSTIC_H) tree-iterator.h
+
+c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(C_PRAGMA_H) $(FLAGS_H) toplev.h langhooks.h \
+ $(TREE_INLINE_H) $(DIAGNOSTIC_H) intl.h debug.h $(C_COMMON_H) \
+ opts.h options.h $(MKDEPS_H) c-incpath.h cppdefault.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
$< $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@
c-cppbuiltin.o : c-cppbuiltin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(C_COMMON_H) c-pragma.h flags.h toplev.h langhooks.h \
- output.h except.h real.h $(TM_P_H)
+ $(TREE_H) version.h $(C_COMMON_H) $(C_PRAGMA_H) $(FLAGS_H) toplev.h \
+ output.h except.h $(REAL_H) $(TARGET_H) $(TM_P_H)
# A file used by all variants of C and some other languages.
-attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) flags.h \
- toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) $(EXPR_H) $(TM_P_H) \
- builtin-types.def $(TARGET_H) langhooks.h
+attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(FLAGS_H) toplev.h output.h $(RTL_H) $(GGC_H) $(TM_P_H) \
+ $(TARGET_H) langhooks.h $(CPPLIB_H)
c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) langhooks.h \
- $(C_COMMON_H) flags.h toplev.h intl.h $(DIAGNOSTIC_H)
+ $(C_COMMON_H) $(FLAGS_H) toplev.h intl.h $(DIAGNOSTIC_H) c-format.h
-c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
- $(EXPR_H) $(PREDICT_H) tree-inline.h
+c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(FLAGS_H) toplev.h output.h $(RTL_H) $(GGC_H) \
+ $(PREDICT_H) $(TREE_INLINE_H) $(C_COMMON_H) except.h $(FUNCTION_H) \
+ langhooks.h $(SPLAY_TREE_H) $(TIMEVAR_H) $(TREE_GIMPLE_H) \
+ $(VARRAY_H)
c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) tree-dump.h
+ $(C_TREE_H) $(TREE_DUMP_H)
c-pch.o : c-pch.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CPPLIB_H) $(TREE_H) \
- $(C_COMMON_H) output.h toplev.h c-pragma.h $(GGC_H) debug.h \
- langhooks.h flags.h hosthooks.h version.h $(TARGET_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(C_COMMON_H) output.h toplev.h $(C_PRAGMA_H) $(GGC_H) debug.h \
+ langhooks.h $(FLAGS_H) hosthooks.h version.h $(TARGET_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
-DHOST_MACHINE=\"$(host)\" -DTARGET_MACHINE=\"$(target)\" \
$< $(OUTPUT_OPTION)
+c-omp.o : c-omp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(FUNCTION_H) $(C_COMMON_H) toplev.h $(TREE_GIMPLE_H)
+
# Language-independent files.
DRIVER_DEFINES = \
@@ -1427,41 +1717,29 @@ DRIVER_DEFINES = \
`test "X$${SHLIB_MULTILIB}" = "X" || echo "-DNO_SHARED_LIBGCC_MULTILIB"`
gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h multilib.h \
- Makefile $(lang_specs_files) specs.h prefix.h $(GCC_H)
+ Makefile $(lang_specs_files) specs.h prefix.h $(GCC_H) $(FLAGS_H) \
+ configargs.h $(OBSTACK_H) opts.h
(SHLIB_LINK='$(SHLIB_LINK)' \
SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
-c $(srcdir)/gcc.c $(OUTPUT_OPTION))
gccspec.o: gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H)
(SHLIB_LINK='$(SHLIB_LINK)' \
SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
-c $(srcdir)/gccspec.c $(OUTPUT_OPTION))
cppspec.o: cppspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H)
-tree-check.h: s-check ; @true
-s-check : gencheck$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./gencheck$(build_exeext) > tmp-check.h
- $(SHELL) $(srcdir)/move-if-change tmp-check.h tree-check.h
- $(STAMP) s-check
-
-gencheck$(build_exeext) : gencheck.o $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- gencheck.o $(BUILD_LIBS)
-
-gencheck.o : gencheck.c gencheck.h tree.def $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) $(lang_tree_files)
-
gencheck.h : s-gencheck ; @true
s-gencheck : Makefile
ltf="$(lang_tree_files)"; for f in $$ltf; do \
echo "#include \"$$f\""; \
done | sed 's|$(srcdir)/||' > tmp-gencheck.h
- $(SHELL) $(srcdir)/move-if-change tmp-gencheck.h gencheck.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-gencheck.h gencheck.h
$(STAMP) s-gencheck
specs.h : s-specs ; @true
@@ -1469,425 +1747,926 @@ s-specs : Makefile
lsf="$(lang_specs_files)"; for f in $$lsf; do \
echo "#include \"$$f\""; \
done | sed 's|$(srcdir)/||' > tmp-specs.h
- $(SHELL) $(srcdir)/move-if-change tmp-specs.h specs.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-specs.h specs.h
$(STAMP) s-specs
-options.c: $(lang_opt_files) $(srcdir)/opts.sh options.h intl.h
+optionlist: s-options ; @true
+s-options: $(ALL_OPT_FILES) Makefile $(srcdir)/opt-gather.awk
+ $(AWK) -f $(srcdir)/opt-gather.awk $(ALL_OPT_FILES) > tmp-optionlist
+ $(SHELL) $(srcdir)/../move-if-change tmp-optionlist optionlist
+ $(STAMP) s-options
+
+options.c: optionlist $(srcdir)/opt-functions.awk $(srcdir)/optc-gen.awk
+ $(AWK) -f $(srcdir)/opt-functions.awk -f $(srcdir)/optc-gen.awk \
+ -v header_name="config.h system.h coretypes.h tm.h" < $< > $@
+
+options.h: s-options-h ; @true
+s-options-h: optionlist $(srcdir)/opt-functions.awk $(srcdir)/opth-gen.awk
+ $(AWK) -f $(srcdir)/opt-functions.awk -f $(srcdir)/opth-gen.awk \
+ < $< > tmp-options.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-options.h options.h
+ $(STAMP) $@
-options.h: $(lang_opt_files) $(srcdir)/opts.sh Makefile
- AWK=$(AWK) $(SHELL) $(srcdir)/opts.sh \
- '$(SHELL) $(srcdir)/move-if-change' \
- options.c options.h $(lang_opt_files)
+options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h
+
+gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) -DGCC_DRIVER options.c
dumpvers: dumpvers.c
-version.o: version.c version.h
+version.o: version.c version.h $(DATESTAMP) $(BASEVER) $(DEVPHASE)
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ -DBASEVER=$(BASEVER_s) -DDATESTAMP=$(DATESTAMP_s) \
+ -DDEVPHASE=$(DEVPHASE_s) -c $(srcdir)/version.c $(OUTPUT_OPTION)
-gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h \
- $(HASHTAB_H) $(TREE_H) $(RTL_H) function.h insn-config.h $(EXPR_H) $(OPTABS_H) \
- libfuncs.h debug.h $(GGC_H) bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h \
- cselib.h insn-addr.h
+gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) bitmap.h $(TREE_H) $(RTL_H) \
+ $(FUNCTION_H) insn-config.h $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) \
+ cselib.h insn-addr.h $(OPTABS_H) libfuncs.h debug.h $(GGC_H) \
+ $(CGRAPH_H) $(TREE_FLOW_H) reload.h $(CPP_ID_DATA_H)
ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
- $(HASHTAB_H) toplev.h $(PARAMS_H) hosthooks.h
-
-ggc-simple.o: ggc-simple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
+ $(HASHTAB_H) toplev.h $(PARAMS_H) hosthooks.h $(HOSTHOOKS_DEF_H)
ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h toplev.h $(GGC_H) $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
+ $(FLAGS_H) toplev.h $(GGC_H) $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H) $(TREE_FLOW_H)
-ggc-zone.o: ggc-zone.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h toplev.h $(GGC_H) $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
+ggc-zone.o: ggc-zone.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) toplev.h $(GGC_H) $(TIMEVAR_H) $(TM_P_H) \
+ $(PARAMS_H) bitmap.h $(VARRAY_H)
-stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(GGC_H) gt-stringpool.h
+ggc-none.o: ggc-none.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
+ $(BCONFIG_H)
-ggc-none.o: ggc-none.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) $(GGC_H)
- $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(GGC_H) gt-stringpool.h $(CPPLIB_H) $(SYMTAB_H)
-prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) Makefile prefix.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- -DPREFIX=\"$(prefix)\" \
+prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) prefix.h \
+ Makefile $(BASEVER)
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ -DPREFIX=\"$(prefix)\" -DBASEVER=$(BASEVER_s) \
-c $(srcdir)/prefix.c $(OUTPUT_OPTION)
-convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) flags.h \
- convert.h toplev.h langhooks.h
+convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(FLAGS_H) convert.h toplev.h langhooks.h $(REAL_H)
-langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) toplev.h \
- tree-inline.h $(RTL_H) insn-config.h $(INTEGRATE_H) langhooks.h \
- $(LANGHOOKS_DEF_H) flags.h $(GGC_H) gt-langhooks.h diagnostic.h
-tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) flags.h function.h \
+double-int.o: double-int.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H)
+
+langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) toplev.h $(TREE_INLINE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) \
+ langhooks.h $(LANGHOOKS_DEF_H) $(FLAGS_H) $(GGC_H) $(DIAGNOSTIC_H) intl.h \
+ $(TREE_GIMPLE_H)
+tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(FLAGS_H) $(FUNCTION_H) $(PARAMS_H) \
toplev.h $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
- real.h gt-tree.h
-tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) flags.h langhooks.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
- $(EXPR_H) $(SPLAY_TREE_H) tree-dump.h
+ $(REAL_H) gt-tree.h tree-iterator.h $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
+ $(OBSTACK_H) pointer-set.h
+tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) langhooks.h toplev.h $(SPLAY_TREE_H) $(TREE_DUMP_H) \
+ tree-iterator.h tree-pass.h $(DIAGNOSTIC_H) $(REAL_H)
tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(RTL_H) $(EXPR_H) flags.h $(PARAMS_H) input.h insn-config.h \
- $(INTEGRATE_H) $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \
- langhooks.h $(C_COMMON_H) tree-inline.h cgraph.h intl.h
-tree-optimize.o : tree-optimize.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) toplev.h langhooks.h cgraph.h $(TIMEVAR_H) function.h $(GGC_H)
-
+ $(TREE_H) $(RTL_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h insn-config.h \
+ $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \
+ langhooks.h $(TREE_INLINE_H) $(CGRAPH_H) intl.h $(FUNCTION_H) $(TREE_GIMPLE_H) \
+ debug.h $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-iterator.h tree-mudflap.h \
+ ipa-prop.h
print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(GGC_H) langhooks.h real.h
-stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- flags.h function.h $(EXPR_H) $(RTL_H) toplev.h $(GGC_H) $(TM_P_H) $(TARGET_H) \
+ $(GGC_H) langhooks.h $(REAL_H) tree-iterator.h
+stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(PARAMS_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(RTL_H) \
+ $(GGC_H) $(TM_P_H) $(TARGET_H) langhooks.h $(REGS_H) gt-stor-layout.h \
+ toplev.h
+tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
+ $(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
+ $(TM_H) coretypes.h $(CGRAPH_H) tree-pass.h $(TIMEVAR_H) \
+ gt-tree-ssa-structalias.h $(PARAMS_H)
+tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
+ toplev.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+ $(TREE_DUMP_H) langhooks.h tree-pass.h $(BASIC_BLOCK_H) bitmap.h \
+ $(FLAGS_H) $(GGC_H) hard-reg-set.h $(HASHTAB_H) pointer-set.h \
+ $(TREE_GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H)
+tree-into-ssa.o : tree-into-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
+ $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ langhooks.h domwalk.h tree-pass.h $(GGC_H) $(PARAMS_H) $(BASIC_BLOCK_H) \
+ bitmap.h $(CFGLOOP_H) $(FLAGS_H) hard-reg-set.h $(HASHTAB_H) \
+ $(TREE_GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H) vecprim.h
+tree-outof-ssa.o : tree-outof-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
+ $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ langhooks.h tree-pass.h $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) bitmap.h \
+ $(FLAGS_H) $(GGC_H) hard-reg-set.h $(HASHTAB_H) $(TREE_GIMPLE_H) \
+ $(TREE_INLINE_H) $(VARRAY_H) toplev.h vecprim.h
+tree-ssa-dse.o : tree-ssa-dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
+ $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) domwalk.h $(FLAGS_H) \
+ $(DIAGNOSTIC_H) $(TIMEVAR_H)
+tree-ssa-forwprop.o : tree-ssa-forwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
+ $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
+ langhooks.h
+tree-ssa-phiopt.o : tree-ssa-phiopt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
+ $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) langhooks.h $(FLAGS_H) \
+ $(DIAGNOSTIC_H) $(TIMEVAR_H)
+tree-nrv.o : tree-nrv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(TREE_H) $(RTL_H) $(FUNCTION_H) $(BASIC_BLOCK_H) $(EXPR_H) \
+ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TIMEVAR_H) $(TREE_DUMP_H) tree-pass.h \
langhooks.h
-fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- flags.h real.h toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) $(GGC_H) $(TM_P_H) langhooks.h
-diagnostic.o : diagnostic.c $(DIAGNOSTIC_H) real.h \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(TM_P_H) flags.h $(GGC_H) \
- input.h toplev.h intl.h langhooks.h $(LANGHOOKS_DEF_H)
+tree-ssa-copy.o : tree-ssa-copy.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h $(DIAGNOSTIC_H) \
+ $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ $(BASIC_BLOCK_H) tree-pass.h langhooks.h tree-ssa-propagate.h $(FLAGS_H)
+tree-ssa-propagate.o : tree-ssa-propagate.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
+ $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+ $(TREE_DUMP_H) $(BASIC_BLOCK_H) tree-pass.h langhooks.h \
+ tree-ssa-propagate.h vec.h gt-tree-ssa-propagate.h $(FLAGS_H) $(VARRAY_H)
+tree-ssa-dom.o : tree-ssa-dom.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h $(DIAGNOSTIC_H) \
+ $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ $(BASIC_BLOCK_H) domwalk.h tree-pass.h $(FLAGS_H) langhooks.h \
+ tree-ssa-propagate.h $(CFGLOOP_H) $(PARAMS_H) $(REAL_H)
+tree-ssa-uncprop.o : tree-ssa-uncprop.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
+ $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+ $(TREE_DUMP_H) $(BASIC_BLOCK_H) domwalk.h tree-pass.h $(FLAGS_H) \
+ langhooks.h tree-ssa-propagate.h $(REAL_H)
+tree-ssa-threadedge.o : tree-ssa-threadedge.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
+ $(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ $(BASIC_BLOCK_H) $(FLAGS_H) tree-pass.h $(CFGLOOP_H)
+tree-ssa-threadupdate.o : tree-ssa-threadupdate.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
+ $(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ $(BASIC_BLOCK_H) $(FLAGS_H) tree-pass.h $(CFGLOOP_H)
+tree-ssanames.o : tree-ssanames.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(TREE_H) $(VARRAY_H) $(GGC_H) gt-tree-ssanames.h $(TREE_FLOW_H)
+tree-phinodes.o : tree-phinodes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(TREE_H) $(VARRAY_H) $(GGC_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
+ gt-tree-phinodes.h $(RTL_H) toplev.h
+domwalk.o : domwalk.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) domwalk.h $(GGC_H)
+tree-ssa-live.o : tree-ssa-live.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) \
+ $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) \
+ bitmap.h $(FLAGS_H) $(HASHTAB_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) \
+ $(VARRAY_H) toplev.h vecprim.h
+tree-ssa-copyrename.o : tree-ssa-copyrename.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) tree-pass.h \
+ $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) \
+ bitmap.h $(FLAGS_H) $(HASHTAB_H) langhooks.h $(TREE_GIMPLE_H) \
+ $(TREE_INLINE_H)
+tree-ssa-pre.o : tree-ssa-pre.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
+ $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(CFGLOOP_H) \
+ alloc-pool.h $(BASIC_BLOCK_H) bitmap.h $(HASHTAB_H) $(TREE_GIMPLE_H) \
+ $(TREE_INLINE_H) tree-iterator.h
+tree-vn.o : tree-vn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
+ $(TREE_H) $(TREE_FLOW_H) $(HASHTAB_H) langhooks.h tree-pass.h \
+ $(TREE_DUMP_H) $(DIAGNOSTIC_H)
+tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(GGC_H) \
+ $(BASIC_BLOCK_H) tree-ssa-propagate.h $(FLAGS_H) $(TREE_DUMP_H) \
+ $(CFGLOOP_H) $(SCEV_H) tree-chrec.h $(TIMEVAR_H) toplev.h intl.h
+tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
+ $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+ $(TREE_DUMP_H) except.h langhooks.h $(CFGLOOP_H) tree-pass.h \
+ $(CFGLAYOUT_H) $(BASIC_BLOCK_H) hard-reg-set.h $(HASHTAB_H) toplev.h \
+ tree-ssa-propagate.h
+tree-cfgcleanup.o : tree-cfgcleanup.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
+ $(DIAGNOSTIC_H) toplev.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+ $(TREE_DUMP_H) except.h langhooks.h $(CFGLOOP_H) tree-pass.h \
+ $(CFGLAYOUT_H) $(BASIC_BLOCK_H) hard-reg-set.h $(HASHTAB_H) toplev.h \
+ tree-ssa-propagate.h
+rtl-factoring.o : rtl-factoring.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
+ coretypes.h $(TM_H) $(BASIC_BLOCK_H) $(GGC_H) $(REGS_H) $(PARAMS_H) $(EXPR_H) \
+ addresses.h $(TM_P_H) tree-pass.h $(TREE_FLOW_H) $(TIMEVAR_H) output.h
+tree-tailcall.o : tree-tailcall.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(FUNCTION_H) $(TM_H) coretypes.h \
+ $(TREE_DUMP_H) $(DIAGNOSTIC_H) except.h tree-pass.h $(FLAGS_H) langhooks.h \
+ $(BASIC_BLOCK_H) hard-reg-set.h
+tree-ssa-sink.o : tree-ssa-sink.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
+ $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) alloc-pool.h \
+ $(BASIC_BLOCK_H) bitmap.h $(CFGLOOP_H) $(FIBHEAP_H) $(HASHTAB_H) \
+ langhooks.h $(REAL_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) tree-iterator.h
+tree-nested.o: tree-nested.c $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) \
+ $(RTL_H) $(TM_P_H) $(FUNCTION_H) $(TREE_DUMP_H) $(TREE_INLINE_H) \
+ tree-iterator.h $(TREE_GIMPLE_H) $(CGRAPH_H) $(EXPR_H) langhooks.h \
+ $(GGC_H) gt-tree-nested.h coretypes.h $(TREE_FLOW_H)
+tree-if-conv.o: tree-if-conv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(FLAGS_H) $(TIMEVAR_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
+ $(CFGLOOP_H) $(RTL_H) $(C_COMMON_H) tree-chrec.h $(TREE_DATA_REF_H) \
+ $(SCEV_H) tree-pass.h $(DIAGNOSTIC_H) $(TARGET_H) $(TREE_DUMP_H) \
+ $(VARRAY_H)
+tree-iterator.o : tree-iterator.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
+ coretypes.h $(GGC_H) tree-iterator.h $(TREE_GIMPLE_H) gt-tree-iterator.h
+tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h $(DIAGNOSTIC_H) \
+ $(TREE_INLINE_H) $(HASHTAB_H) pointer-set.h $(FLAGS_H) $(FUNCTION_H) \
+ $(TIMEVAR_H) convert.h $(TM_H) coretypes.h langhooks.h $(TREE_DUMP_H) \
+ tree-pass.h $(PARAMS_H) $(CGRAPH_H) $(BASIC_BLOCK_H) hard-reg-set.h \
+ $(TREE_GIMPLE_H)
+tree-ssa-operands.o : tree-ssa-operands.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) errors.h $(TREE_INLINE_H) \
+ $(FLAGS_H) $(FUNCTION_H) $(TM_H) $(TIMEVAR_H) tree-pass.h toplev.h \
+ gt-tree-ssa-operands.h coretypes.h langhooks.h $(IPA_REFERENCE_H)
+tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) except.h langhooks.h \
+ $(GGC_H) tree-pass.h coretypes.h $(TIMEVAR_H) $(TM_P_H) \
+ $(TREE_DUMP_H) $(TREE_INLINE_H) tree-iterator.h toplev.h
+tree-ssa-loop.o : tree-ssa-loop.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) \
+ output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ tree-pass.h $(FLAGS_H) $(TREE_INLINE_H) $(SCEV_H) $(BASIC_BLOCK_H) \
+ hard-reg-set.h
+tree-ssa-loop-unswitch.o : tree-ssa-loop-unswitch.c $(TREE_FLOW_H) \
+ $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) \
+ domwalk.h $(PARAMS_H) output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) \
+ coretypes.h $(TREE_DUMP_H) tree-pass.h $(BASIC_BLOCK_H) hard-reg-set.h
+tree-ssa-address.o : tree-ssa-address.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) \
+ output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ tree-pass.h $(FLAGS_H) $(TREE_INLINE_H) $(RECOG_H) insn-config.h $(EXPR_H) \
+ gt-tree-ssa-address.h $(GGC_H)
+tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
+ $(TREE_INLINE_H) output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ $(FLAGS_H) tree-pass.h $(SCEV_H) $(TREE_DATA_REF_H) $(BASIC_BLOCK_H) \
+ $(GGC_H) hard-reg-set.h tree-chrec.h intl.h
+tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
+ $(TREE_INLINE_H) output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ $(FLAGS_H) tree-pass.h $(SCEV_H) $(BASIC_BLOCK_H) $(GGC_H) hard-reg-set.h \
+ tree-chrec.h
+tree-ssa-loop-ch.o : tree-ssa-loop-ch.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(TREE_INLINE_H) \
+ output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ tree-pass.h $(FLAGS_H) $(BASIC_BLOCK_H) hard-reg-set.h
+tree-ssa-loop-prefetch.o: tree-ssa-loop-prefetch.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(EXPR_H) \
+ output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ tree-pass.h $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \
+ $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) hard-reg-set.h \
+ tree-chrec.h toplev.h langhooks.h
+tree-ssa-loop-ivopts.o : tree-ssa-loop-ivopts.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(EXPR_H) \
+ output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ tree-pass.h $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \
+ $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) hard-reg-set.h \
+ tree-chrec.h $(VARRAY_H)
+tree-ssa-loop-manip.o : tree-ssa-loop-manip.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) \
+ output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ tree-pass.h $(CFGLAYOUT_H) $(SCEV_H) $(BASIC_BLOCK_H) hard-reg-set.h \
+ $(PARAMS_H)
+tree-ssa-loop-im.o : tree-ssa-loop-im.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) domwalk.h \
+ $(PARAMS_H) output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+ $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(REAL_H) $(BASIC_BLOCK_H) \
+ hard-reg-set.h
+tree-ssa-math-opts.o : tree-ssa-math-opts.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(TREE_H) $(TIMEVAR_H) tree-pass.h $(TM_H) $(FLAGS_H) \
+ alloc-pool.h $(BASIC_BLOCK_H) $(TARGET_H)
+tree-ssa-alias.o : tree-ssa-alias.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(TREE_INLINE_H) $(FLAGS_H) \
+ $(FUNCTION_H) $(TIMEVAR_H) convert.h $(TM_H) coretypes.h langhooks.h \
+ $(TREE_DUMP_H) tree-pass.h $(PARAMS_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) \
+ hard-reg-set.h $(TREE_GIMPLE_H) vec.h tree-ssa-structalias.h \
+ $(IPA_TYPE_ESCAPE_H) vecprim.h pointer-set.h
+tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) errors.h $(TIMEVAR_H) \
+ $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) tree-iterator.h\
+ $(BASIC_BLOCK_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) vec.h \
+ alloc-pool.h
+tree-optimize.o : tree-optimize.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h $(DIAGNOSTIC_H) \
+ $(FLAGS_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) toplev.h \
+ $(FUNCTION_H) langhooks.h $(FLAGS_H) $(CGRAPH_H) $(TREE_INLINE_H) \
+ tree-mudflap.h $(GGC_H) $(CGRAPH_H) tree-pass.h $(CFGLOOP_H) \
+ $(BASIC_BLOCK_H) graph.h hard-reg-set.h
+c-gimplify.o : c-gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
+ $(C_TREE_H) $(C_COMMON_H) $(DIAGNOSTIC_H) $(TREE_GIMPLE_H) $(VARRAY_H) \
+ $(FLAGS_H) langhooks.h toplev.h $(RTL_H) $(TREE_FLOW_H) $(LANGHOOKS_DEF_H) \
+ $(TM_H) coretypes.h $(C_PRETTY_PRINT_H) $(CGRAPH_H) $(BASIC_BLOCK_H) \
+ hard-reg-set.h $(TREE_DUMP_H) $(TREE_INLINE_H)
+gimplify.o : gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
+ $(DIAGNOSTIC_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H) langhooks.h \
+ $(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(CGRAPH_H) $(TIMEVAR_H) $(TM_H) \
+ coretypes.h except.h $(FLAGS_H) $(RTL_H) $(FUNCTION_H) $(EXPR_H) output.h \
+ $(GGC_H) gt-gimplify.h $(HASHTAB_H) $(TARGET_H) toplev.h $(OPTABS_H) \
+ $(REAL_H)
+gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
+ $(DIAGNOSTIC_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) $(VARRAY_H) langhooks.h \
+ $(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+ except.h $(FLAGS_H) $(RTL_H) $(FUNCTION_H) $(EXPR_H) tree-pass.h \
+ $(HASHTAB_H) toplev.h
+omp-low.o : omp-low.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(RTL_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) langhooks.h $(DIAGNOSTIC_H) \
+ $(TREE_FLOW_H) $(TIMEVAR_H) $(FLAGS_H) $(EXPR_H) toplev.h tree-pass.h \
+ $(GGC_H)
+tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) \
+ $(TM_H) coretypes.h
+tree-chrec.o: tree-chrec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(GGC_H) $(TREE_H) $(REAL_H) $(SCEV_H) tree-pass.h $(PARAMS_H) \
+ $(DIAGNOSTIC_H) $(CFGLOOP_H) $(TREE_FLOW_H)
+tree-scalar-evolution.o: tree-scalar-evolution.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(REAL_H) $(RTL_H) \
+ $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) \
+ $(TIMEVAR_H) $(CFGLOOP_H) $(SCEV_H) tree-pass.h $(FLAGS_H) tree-chrec.h
+tree-data-ref.o: tree-data-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(GGC_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) \
+ $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
+ $(TREE_DATA_REF_H) $(SCEV_H) tree-pass.h tree-chrec.h
+tree-vect-analyze.o: tree-vect-analyze.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(GGC_H) $(OPTABS_H) $(TREE_H) $(BASIC_BLOCK_H) \
+ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
+ tree-vectorizer.h $(TREE_DATA_REF_H) $(SCEV_H) $(EXPR_H) tree-chrec.h
+tree-vect-patterns.o: tree-vect-patterns.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) errors.h $(GGC_H) $(OPTABS_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) \
+ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
+ tree-vectorizer.h $(TREE_DATA_REF_H) $(EXPR_H) $(TARGET_H)
+tree-vect-transform.o: tree-vect-transform.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(GGC_H) $(OPTABS_H) $(RECOG_H) $(TREE_H) $(RTL_H) \
+ $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) \
+ $(TIMEVAR_H) $(CFGLOOP_H) $(TARGET_H) tree-pass.h $(EXPR_H) \
+ tree-vectorizer.h $(TREE_DATA_REF_H) $(SCEV_H) langhooks.h toplev.h \
+ tree-chrec.h
+tree-vectorizer.o: tree-vectorizer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(GGC_H) $(OPTABS_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) \
+ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
+ tree-pass.h $(EXPR_H) tree-vectorizer.h $(TREE_DATA_REF_H) $(SCEV_H) \
+ input.h $(TARGET_H) $(CFGLAYOUT_H) toplev.h tree-chrec.h
+tree-loop-linear.o: tree-loop-linear.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(GGC_H) $(OPTABS_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) \
+ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
+ tree-pass.h $(TREE_DATA_REF_H) $(SCEV_H) $(EXPR_H) $(LAMBDA_H) \
+ $(TARGET_H) tree-chrec.h
+tree-stdarg.o: tree-stdarg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(FUNCTION_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-pass.h \
+ tree-stdarg.h $(TARGET_H) langhooks.h
+tree-object-size.o: tree-object-size.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-pass.h \
+ tree-ssa-propagate.h
+tree-gimple.o : tree-gimple.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(EXPR_H) \
+ $(RTL_H) $(TREE_GIMPLE_H) $(TM_H) coretypes.h bitmap.h $(GGC_H) \
+ output.h $(TREE_FLOW_H)
+tree-mudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \
+ $(TREE_GIMPLE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) langhooks.h tree-mudflap.h \
+ $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(CGRAPH_H) $(GGC_H) \
+ gt-tree-mudflap.h $(BASIC_BLOCK_H) $(FLAGS_H) $(FUNCTION_H) hard-reg-set.h \
+ $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) toplev.h
+tree-nomudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \
+ $(C_TREE_H) $(C_COMMON_H) $(TREE_GIMPLE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) \
+ output.h $(VARRAY_H) langhooks.h tree-mudflap.h $(TM_H) coretypes.h \
+ $(GGC_H) gt-tree-mudflap.h tree-pass.h toplev.h
+tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(DIAGNOSTIC_H) $(REAL_H) $(HASHTAB_H) $(TREE_FLOW_H) \
+ $(TM_H) coretypes.h tree-iterator.h tree-chrec.h langhooks.h tree-pass.h
+fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(FLAGS_H) $(REAL_H) toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) \
+ $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h
+diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) version.h $(TM_P_H) $(FLAGS_H) input.h toplev.h intl.h \
+ $(DIAGNOSTIC_H) langhooks.h $(LANGHOOKS_DEF_H) diagnostic.def opts.h
opts.o : opts.c opts.h options.h toplev.h $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(RTL_H) \
- output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h
-targhooks.o : targhooks.c targhooks.h $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_H) $(TM_H) $(RTL_H) $(TM_P_H) function.h \
- output.h toplev.h
-
-toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
- function.h flags.h xcoffout.h input.h $(INSN_ATTR_H) output.h $(DIAGNOSTIC_H) \
- debug.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h \
- dwarf2out.h sdbout.h dbxout.h $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) \
- graph.h $(LOOP_H) except.h $(REGS_H) $(TIMEVAR_H) value-prof.h \
- $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) \
- langhooks.h insn-flags.h cfglayout.h real.h cfgloop.h \
- hosthooks.h $(LANGHOOKS_DEF_H) cgraph.h $(COVERAGE_H) alloc-pool.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(RTL_H) \
+ output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
+ $(FLAGS_H) $(PARAMS_H) tree-pass.h
+opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h intl.h
+targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
+ $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FUNCTION_H) output.h toplev.h \
+ $(MACHMODE_H) $(TARGET_DEF_H) $(TARGET_H) $(GGC_H) gt-targhooks.h
+
+toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ version.h $(RTL_H) $(FUNCTION_H) $(FLAGS_H) xcoffout.h input.h \
+ $(INSN_ATTR_H) output.h $(DIAGNOSTIC_H) debug.h insn-config.h intl.h \
+ $(RECOG_H) Makefile toplev.h dwarf2out.h sdbout.h dbxout.h $(EXPR_H) \
+ hard-reg-set.h $(BASIC_BLOCK_H) graph.h except.h $(REGS_H) $(TIMEVAR_H) \
+ value-prof.h $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) \
+ langhooks.h insn-flags.h $(CFGLAYOUT_H) $(CFGLOOP_H) hosthooks.h \
+ $(CGRAPH_H) $(COVERAGE_H) alloc-pool.h $(GGC_H) $(INTEGRATE_H) \
+ $(CPPLIB_H) opts.h params.def tree-mudflap.h $(REAL_H)
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_NAME=\"$(target_noncanonical)\" \
-c $(srcdir)/toplev.c $(OUTPUT_OPTION)
+
+passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(RTL_H) $(FUNCTION_H) $(FLAGS_H) xcoffout.h input.h $(INSN_ATTR_H) output.h \
+ $(DIAGNOSTIC_H) debug.h insn-config.h intl.h $(RECOG_H) toplev.h \
+ dwarf2out.h sdbout.h dbxout.h $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) \
+ graph.h except.h $(REGS_H) $(TIMEVAR_H) value-prof.h \
+ $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) \
+ langhooks.h insn-flags.h $(CFGLAYOUT_H) $(REAL_H) $(CFGLOOP_H) \
+ hosthooks.h $(CGRAPH_H) $(COVERAGE_H) tree-pass.h $(TREE_DUMP_H) \
+ $(GGC_H) $(INTEGRATE_H) $(CPPLIB_H) opts.h $(TREE_FLOW_H) $(TREE_INLINE_H)
+
main.o : main.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h
host-default.o : host-default.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- hosthooks.h hosthooks-def.h
+ hosthooks.h $(HOSTHOOKS_DEF_H)
-rtl-error.o: rtl-error.c $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(INSN_ATTR_H) \
- insn-config.h input.h toplev.h intl.h $(DIAGNOSTIC_H) $(CONFIG_H)
+rtl-error.o: rtl-error.c $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(INSN_ATTR_H) insn-config.h input.h toplev.h intl.h $(DIAGNOSTIC_H) \
+ $(CONFIG_H)
-rtl.o : rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) $(RTL_H) real.h \
- $(GGC_H) errors.h
- $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+rtl.o : rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(GGC_H) $(BCONFIG_H) insn-notes.def reg-notes.def toplev.h $(REAL_H)
print-rtl.o : print-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(TREE_H) hard-reg-set.h $(BASIC_BLOCK_H) real.h $(TM_P_H)
+ $(RTL_H) $(TREE_H) hard-reg-set.h $(BASIC_BLOCK_H) $(FLAGS_H) \
+ $(BCONFIG_H) $(REAL_H)
rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \
- $(RTL_H) hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) real.h flags.h \
- $(BASIC_BLOCK_H)
-
-errors.o : errors.c $(CONFIG_H) $(SYSTEM_H) errors.h
- $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-
-varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
- flags.h function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \
- output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
- $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h
-function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \
- insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
- $(TM_P_H) langhooks.h gt-function.h $(TARGET_H)
-stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
- function.h insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
- $(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H) \
- langhooks.h $(PREDICT_H) gt-stmt.h $(OPTABS_H) $(TARGET_H)
+ $(RTL_H) hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) $(REAL_H) \
+ $(FLAGS_H) $(REGS_H) output.h $(TARGET_H) $(FUNCTION_H)
+
+varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(RTL_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) hard-reg-set.h $(REGS_H) \
+ output.h $(C_PRAGMA_H) toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
+ $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h $(BASIC_BLOCK_H) \
+ $(CFGLAYOUT_H) $(CGRAPH_H) tree-mudflap.h $(REAL_H)
+function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(CFGLAYOUT_H) $(TREE_GIMPLE_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) \
+ $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
+ output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) $(TM_P_H) langhooks.h \
+ gt-function.h $(TARGET_H) $(BASIC_BLOCK_H) $(INTEGRATE_H) $(PREDICT_H) \
+ tree-pass.h vecprim.h
+stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) $(FUNCTION_H) insn-config.h hard-reg-set.h $(EXPR_H) \
+ libfuncs.h except.h $(RECOG_H) toplev.h output.h $(GGC_H) $(TM_P_H) \
+ langhooks.h $(PREDICT_H) $(OPTABS_H) $(TARGET_H) $(MACHMODE_H) \
+ $(REGS_H)
except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) flags.h except.h function.h $(EXPR_H) libfuncs.h $(INTEGRATE_H) \
+ $(TREE_H) $(FLAGS_H) except.h $(FUNCTION_H) $(EXPR_H) libfuncs.h \
langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
dwarf2asm.h dwarf2out.h toplev.h $(HASHTAB_H) intl.h $(GGC_H) \
- gt-except.h cgraph.h
-expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
- function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h $(INSN_ATTR_H) insn-config.h \
- $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
- except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H) real.h $(TARGET_H)
+ gt-except.h $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) dwarf2.h \
+ $(TARGET_H) $(TM_P_H) tree-pass.h $(TIMEVAR_H)
+expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \
+ libfuncs.h $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \
+ typeclass.h hard-reg-set.h toplev.h hard-reg-set.h except.h reload.h \
+ $(GGC_H) langhooks.h intl.h $(TM_P_H) $(REAL_H) $(TARGET_H) \
+ tree-iterator.h gt-expr.h $(MACHMODE_H) $(TIMEVAR_H) $(TREE_FLOW_H) \
+ tree-pass.h
dojump.o : dojump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h function.h $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \
+ $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \
langhooks.h $(GGC_H) gt-dojump.h
-builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H)\
- flags.h $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
- $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
- except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h
-calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
- $(EXPR_H) $(OPTABS_H) langhooks.h $(TARGET_H) \
- libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) cgraph.h except.h
+builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(TREE_GIMPLE_H) $(FLAGS_H) $(TARGET_H) $(FUNCTION_H) $(REGS_H) \
+ $(EXPR_H) $(OPTABS_H) insn-config.h $(RECOG_H) output.h typeclass.h \
+ hard-reg-set.h toplev.h hard-reg-set.h except.h $(TM_P_H) $(PREDICT_H) \
+ libfuncs.h $(REAL_H) langhooks.h $(BASIC_BLOCK_H) tree-mudflap.h \
+ $(BUILTINS_DEF) $(MACHMODE_H)
+calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) langhooks.h $(TARGET_H) \
+ libfuncs.h $(REGS_H) toplev.h output.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_P_H) \
+ $(CGRAPH_H) except.h sbitmap.h
expmed.o : expmed.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) real.h \
+ $(FLAGS_H) insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) $(REAL_H) \
toplev.h $(TM_P_H) langhooks.h
explow.o : explow.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h hard-reg-set.h insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
- toplev.h function.h $(GGC_H) $(TM_P_H) langhooks.h gt-explow.h
-optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h insn-config.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(RECOG_H) reload.h \
- toplev.h $(GGC_H) real.h $(TM_P_H) except.h gt-optabs.h $(BASIC_BLOCK_H) \
- $(TARGET_H)
-dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
- flags.h $(REGS_H) debug.h $(TM_P_H) $(TARGET_H) function.h langhooks.h \
- insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h \
- $(GGC_H) gt-dbxout.h
+ $(FLAGS_H) hard-reg-set.h insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
+ toplev.h $(FUNCTION_H) $(GGC_H) $(TM_P_H) langhooks.h gt-explow.h \
+ $(TARGET_H) output.h
+optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) insn-config.h $(EXPR_H) $(OPTABS_H) libfuncs.h \
+ $(RECOG_H) reload.h toplev.h $(GGC_H) $(REAL_H) $(TM_P_H) except.h \
+ gt-optabs.h $(BASIC_BLOCK_H) $(TARGET_H) $(FUNCTION_H)
+dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(RTL_H) $(FLAGS_H) $(REGS_H) debug.h $(TM_P_H) $(TARGET_H) $(FUNCTION_H) \
+ langhooks.h insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h \
+ toplev.h $(GGC_H) $(OBSTACK_H) $(EXPR_H) gt-dbxout.h
debug.o : debug.c debug.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
-sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
- flags.h function.h $(EXPR_H) output.h hard-reg-set.h $(REGS_H) real.h \
- insn-config.h xcoffout.h c-pragma.h $(GGC_H) $(TARGET_H) \
- sdbout.h toplev.h $(TM_P_H) except.h debug.h langhooks.h gt-sdbout.h
-dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) dwarf2.h debug.h flags.h insn-config.h reload.h output.h $(DIAGNOSTIC_H) real.h \
- hard-reg-set.h $(REGS_H) $(EXPR_H) libfuncs.h toplev.h dwarf2out.h varray.h \
- $(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) \
- gt-dwarf2out.h $(TARGET_H) cgraph.h
-dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) flags.h $(RTL_H) \
- $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) gt-dwarf2asm.h
-vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) flags.h output.h vmsdbg.h debug.h langhooks.h function.h $(TARGET_H)
-xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
- xcoffout.h flags.h toplev.h output.h dbxout.h $(GGC_H) $(TARGET_H)
-emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h function.h $(REGS_H) insn-config.h $(RECOG_H) real.h $(GGC_H) \
- $(EXPR_H) $(OBSTACK_H) hard-reg-set.h bitmap.h toplev.h \
- $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h gt-emit-rtl.h
-real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) toplev.h $(TM_P_H)
-integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h debug.h $(INTEGRATE_H) insn-config.h $(EXPR_H) real.h $(REGS_H) \
- intl.h function.h output.h $(RECOG_H) except.h toplev.h $(LOOP_H) \
- $(PARAMS_H) $(TM_P_H) $(TARGET_H) langhooks.h gt-integrate.h
-jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- hard-reg-set.h $(REGS_H) insn-config.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \
- toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h $(PREDICT_H) $(TIMEVAR_H) \
- $(DIAGNOSTIC_H)
-
-simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(REGS_H) hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
- output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H) $(TREE_H) $(TARGET_H)
+sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) debug.h \
+ $(TREE_H) $(GGC_H) $(RTL_H) $(REGS_H) $(FLAGS_H) insn-config.h \
+ output.h toplev.h $(TM_P_H) gsyms.h langhooks.h $(TARGET_H) sdbout.h \
+ gt-sdbout.h reload.h $(VARRAY_H)
+dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) version.h $(RTL_H) dwarf2.h debug.h $(FLAGS_H) insn-config.h \
+ output.h $(DIAGNOSTIC_H) $(REAL_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
+ libfuncs.h toplev.h dwarf2out.h reload.h $(GGC_H) except.h dwarf2asm.h \
+ $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) \
+ $(MD5_H) input.h $(FUNCTION_H) $(VARRAY_H)
+dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(FLAGS_H) $(RTL_H) $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) \
+ gt-dwarf2asm.h dwarf2.h $(SPLAY_TREE_H) $(TARGET_H)
+vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) version.h \
+ $(RTL_H) $(FLAGS_H) output.h vmsdbg.h debug.h langhooks.h $(FUNCTION_H) $(TARGET_H)
+xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) $(RTL_H) xcoffout.h $(FLAGS_H) toplev.h output.h dbxout.h \
+ $(GGC_H) $(TARGET_H) gstab.h xcoff.h
+emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) \
+ $(GGC_H) $(EXPR_H) hard-reg-set.h bitmap.h toplev.h $(BASIC_BLOCK_H) \
+ $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h tree-pass.h gt-emit-rtl.h \
+ $(REAL_H)
+real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ toplev.h $(TM_P_H) $(REAL_H)
+dfp.o : dfp.c dfp.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ toplev.h $(TM_P_H) $(REAL_H) $(DECNUM_H)
+integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(TREE_H) $(FLAGS_H) debug.h $(INTEGRATE_H) insn-config.h \
+ $(EXPR_H) $(REAL_H) $(REGS_H) intl.h $(FUNCTION_H) output.h $(RECOG_H) \
+ except.h toplev.h $(PARAMS_H) $(TM_P_H) $(TARGET_H) langhooks.h \
+ gt-integrate.h $(GGC_H) tree-pass.h
+jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) hard-reg-set.h $(REGS_H) insn-config.h $(RECOG_H) $(EXPR_H) \
+ $(REAL_H) except.h $(FUNCTION_H) tree-pass.h $(DIAGNOSTIC_H) \
+ toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h $(PREDICT_H) \
+ $(TIMEVAR_H) $(TARGET_H)
+simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h \
+ $(RECOG_H) $(EXPR_H) toplev.h output.h $(FUNCTION_H) $(GGC_H) $(TM_P_H) \
+ $(TREE_H) $(TARGET_H)
cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- langhooks.h toplev.h flags.h $(GGC_H) $(TARGET_H) cgraph.h gt-cgraph.h \
- output.h intl.h
-cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- langhooks.h tree-inline.h toplev.h flags.h $(GGC_H) $(TARGET_H) cgraph.h intl.h \
- function.h
-coverage.o : coverage.c gcov-io.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(TREE_H) flags.h output.h $(REGS_H) $(EXPR_H) function.h \
- toplev.h $(GGC_H) $(TARGET_H) langhooks.h $(COVERAGE_H) libfuncs.h \
- gt-coverage.h $(HASHTAB_H)
-cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
- hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
- output.h function.h cselib.h $(GGC_H) $(TM_P_H) gt-cselib.h $(PARAMS_H)
+ langhooks.h toplev.h $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
+ gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
+ $(TREE_INLINE_H) $(VARRAY_H) $(TREE_DUMP_H)
+cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(FLAGS_H) $(GGC_H) \
+ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(TREE_GIMPLE_H) \
+ $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \
+ $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h \
+ gt-cgraphunit.h
+ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H)
+ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) ipa-prop.h \
+ $(TREE_FLOW_H) $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H)
+ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ langhooks.h $(TARGET_H) $(CGRAPH_H) ipa-prop.h \
+ $(TREE_FLOW_H) $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H) $(DIAGNOSTIC_H)
+ipa-inline.o : ipa-inline.c gt-ipa-inline.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
+ $(DIAGNOSTIC_H) $(FIBHEAP_H) $(PARAMS_H) $(TIMEVAR_H) tree-pass.h \
+ $(COVERAGE_H) $(HASHTAB_H)
+ipa-utils.o : ipa-utils.c $(IPA_UTILS_H) $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \
+ pointer-set.h $(GGC_H) $(C_COMMON_H) $(TREE_GIMPLE_H) \
+ $(CGRAPH_H) output.h $(FLAGS_H) tree-pass.h $(DIAGNOSTIC_H)
+ipa-reference.o : ipa-reference.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \
+ pointer-set.h $(GGC_H) $(IPA_REFERENCE_H) $(IPA_UTILS_H) $(C_COMMON_H) \
+ $(TREE_GIMPLE_H) $(CGRAPH_H) output.h $(FLAGS_H) tree-pass.h \
+ $(DIAGNOSTIC_H) $(FUNCTION_H)
+
+ipa-pure-const.o : ipa-pure-const.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \
+ pointer-set.h $(GGC_H) $(IPA_UTILS_H) $(C_COMMON_H) $(TARGET_H) \
+ $(TREE_GIMPLE_H) $(CGRAPH_H) output.h $(FLAGS_H) tree-pass.h $(DIAGNOSTIC_H)
+ipa-type-escape.o : ipa-type-escape.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \
+ pointer-set.h $(GGC_H) $(IPA_TYPE_ESCAPE_H) $(IPA_UTILS_H) $(C_COMMON_H) \
+ $(TREE_GIMPLE_H) $(CGRAPH_H) output.h $(FLAGS_H) tree-pass.h \
+ $(DIAGNOSTIC_H) $(FUNCTION_H)
+
+coverage.o : coverage.c $(GCOV_IO_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \
+ $(FUNCTION_H) toplev.h $(GGC_H) langhooks.h $(COVERAGE_H) gt-coverage.h \
+ $(HASHTAB_H) $(CGRAPH_H) tree-iterator.h
+cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(RECOG_H) \
+ $(EMIT_RTL_H) toplev.h output.h $(FUNCTION_H) cselib.h $(GGC_H) $(TM_P_H) \
+ gt-cselib.h $(PARAMS_H) alloc-pool.h $(HASHTAB_H) $(TARGET_H)
cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
- hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
- output.h function.h $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) \
- except.h $(TARGET_H) $(PARAMS_H)
-web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
- hard-reg-set.h flags.h $(BASIC_BLOCK_H) function.h output.h toplev.h df.h
-gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
- hard-reg-set.h flags.h real.h insn-config.h $(GGC_H) $(RECOG_H) $(EXPR_H) \
- $(BASIC_BLOCK_H) function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) \
- except.h gt-gcse.h $(TREE_H) cselib.h
-sibcall.o : sibcall.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
- function.h hard-reg-set.h flags.h insn-config.h $(RECOG_H) $(BASIC_BLOCK_H)
-resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) coretypes.h \
- $(TM_H) $(BASIC_BLOCK_H) $(REGS_H) flags.h output.h resource.h function.h toplev.h \
- $(INSN_ATTR_H) except.h $(PARAMS_H) $(TM_P_H)
+ hard-reg-set.h $(FLAGS_H) insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
+ output.h $(FUNCTION_H) $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) \
+ except.h $(TARGET_H) $(PARAMS_H) rtlhooks-def.h tree-pass.h $(REAL_H)
+web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
+ $(DF_H) $(OBSTACK_H) $(TIMEVAR_H) tree-pass.h
+see.o : see.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
+ $(DF_H) $(OBSTACK_H) $(TIMEVAR_H) tree-pass.h $(EXPR_H)
+gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \
+ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
+ $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h $(TREE_H) cselib.h $(TIMEVAR_H) \
+ intl.h $(OBSTACK_H) tree-pass.h
+resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \
+ coretypes.h $(TM_H) $(REGS_H) $(FLAGS_H) output.h $(RESOURCE_H) \
+ $(FUNCTION_H) toplev.h $(INSN_ATTR_H) except.h $(PARAMS_H) $(TM_P_H)
lcm.o : lcm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
- hard-reg-set.h flags.h real.h insn-config.h $(INSN_ATTR_H) $(RECOG_H) $(EXPR_H) \
- $(BASIC_BLOCK_H) $(TM_P_H) df.h function.h
-df.o : df.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- insn-config.h $(RECOG_H) function.h $(REGS_H) alloc-pool.h hard-reg-set.h \
- $(BASIC_BLOCK_H) df.h $(FIBHEAP_H)
+ hard-reg-set.h $(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(RECOG_H) \
+ $(BASIC_BLOCK_H) $(TM_P_H) $(FUNCTION_H) output.h $(REAL_H)
+mode-switching.o : mode-switching.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
+ $(INSN_ATTR_H) $(RECOG_H) $(BASIC_BLOCK_H) $(TM_P_H) $(FUNCTION_H) \
+ output.h tree-pass.h $(TIMEVAR_H) $(REAL_H)
+tree-ssa-dce.o : tree-ssa-dce.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
+ $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) \
+ coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(BASIC_BLOCK_H) \
+ $(GGC_H) hard-reg-set.h $(OBSTACK_H) $(TREE_GIMPLE_H) $(CFGLOOP_H) \
+ $(SCEV_H)
+tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
+ $(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
+ $(TREE_DUMP_H) $(BASIC_BLOCK_H) tree-pass.h langhooks.h \
+ tree-ssa-propagate.h $(FLAGS_H) $(TARGET_H) toplev.h
+tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \
+ $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
+ $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_GIMPLE_H) \
+ langhooks.h tree-pass.h $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) \
+ bitmap.h $(GGC_H) hard-reg-set.h $(OBSTACK_H) $(PARAMS_H) $(TARGET_H)
+tree-complex.o : tree-complex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
+ $(TM_H) $(RTL_H) $(REAL_H) $(FLAGS_H) $(TREE_FLOW_H) $(TREE_GIMPLE_H) \
+ tree-iterator.h tree-pass.h tree-ssa-propagate.h $(DIAGNOSTIC_H)
+tree-vect-generic.o : tree-vect-generic.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
+ $(TM_H) $(TREE_FLOW_H) $(TREE_GIMPLE_H) tree-iterator.h tree-pass.h \
+ $(FLAGS_H) $(OPTABS_H) $(RTL_H) $(MACHMODE_H) $(EXPR_H) \
+ langhooks.h $(FLAGS_H) $(DIAGNOSTIC_H) gt-tree-vect-generic.h $(GGC_H) \
+ coretypes.h insn-codes.h
+df-core.o : df-core.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
+ hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) bitmap.h sbitmap.h \
+ $(TM_P_H) $(FLAGS_H) output.h tree-pass.h
+df-problems.o : df-problems.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
+ hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) bitmap.h sbitmap.h $(TM_P_H) \
+ $(FLAGS_H) output.h vecprim.h
+df-scan.o : df-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
+ hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) bitmap.h sbitmap.h $(TM_P_H) \
+ $(FLAGS_H) $(TARGET_H) $(TARGET_DEF_H) $(TREE_H) output.h tree-pass.h
+var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \
+ $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \
+ $(REGS_H) $(EXPR_H) $(TIMEVAR_H) tree-pass.h
conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H) \
$(HASHTAB_H) $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H)
profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) flags.h output.h $(REGS_H) $(EXPR_H) function.h \
- toplev.h $(BASIC_BLOCK_H) $(COVERAGE_H) $(TREE_H) value-prof.h
-value-prof.o : value-prof.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h value-prof.h $(EXPR_H) output.h flags.h \
- $(RECOG_H) insn-config.h $(OPTABS_H) $(REGS_H)
-loop.o : loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h $(LOOP_H) \
- insn-config.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) \
- real.h $(PREDICT_H) $(BASIC_BLOCK_H) function.h cfgloop.h \
- toplev.h varray.h except.h cselib.h $(OPTABS_H) $(TM_P_H) $(GGC_H)
-doloop.o : doloop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- $(LOOP_H) $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) toplev.h \
- cfgloop.h
-unroll.o : unroll.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) insn-config.h \
- function.h $(INTEGRATE_H) $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) $(LOOP_H) toplev.h \
- hard-reg-set.h varray.h $(BASIC_BLOCK_H) $(TM_P_H) $(PREDICT_H) $(PARAMS_H) \
- cfgloop.h
+ $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) $(FUNCTION_H) \
+ toplev.h $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h cfghooks.h \
+ $(CFGLOOP_H) $(TIMEVAR_H) tree-pass.h
+tree-profile.o : tree-profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \
+ $(FUNCTION_H) toplev.h $(COVERAGE_H) $(TREE_H) value-prof.h $(TREE_DUMP_H) \
+ tree-pass.h $(TREE_FLOW_H) $(TIMEVAR_H) $(GGC_H) gt-tree-profile.h
+value-prof.o : value-prof.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(BASIC_BLOCK_H) hard-reg-set.h value-prof.h $(EXPR_H) output.h $(FLAGS_H) \
+ $(RECOG_H) insn-config.h $(OPTABS_H) $(REGS_H) $(GGC_H) $(DIAGNOSTIC_H) \
+ $(TREE_H) $(COVERAGE_H) $(RTL_H) $(GCOV_IO_H) $(TREE_FLOW_H) \
+ tree-flow-inline.h $(TIMEVAR_H) tree-pass.h
+loop-doloop.o : loop-doloop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(FLAGS_H) $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) \
+ toplev.h $(CFGLOOP_H) output.h $(PARAMS_H) $(TARGET_H)
alloc-pool.o : alloc-pool.c $(CONFIG_H) $(SYSTEM_H) alloc-pool.h $(HASHTAB_H)
-flow.o : flow.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h \
- $(RECOG_H) function.h except.h $(EXPR_H) $(GGC_H) $(TM_P_H)
-cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h insn-config.h \
- $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
- function.h except.h $(GGC_H) $(TM_P_H) alloc-pool.h
-cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- $(BASIC_BLOCK_H) cfglayout.h
-cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
- function.h except.h $(GGC_H) $(TM_P_H) insn-config.h $(EXPR_H)
+flow.o : flow.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) \
+ hard-reg-set.h output.h toplev.h $(RECOG_H) $(FUNCTION_H) except.h \
+ $(EXPR_H) $(TM_P_H) $(OBSTACK_H) $(SPLAY_TREE_H) $(TIMEVAR_H) tree-pass.h
+cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
+ $(REGS_H) hard-reg-set.h output.h toplev.h $(FUNCTION_H) except.h $(GGC_H) \
+ $(TM_P_H) $(TIMEVAR_H) $(OBSTACK_H) $(TREE_H) alloc-pool.h $(HASHTAB_H)
+cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h
+cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) \
+ coretypes.h $(TREE_DUMP_H) except.h langhooks.h tree-pass.h $(RTL_H) \
+ $(DIAGNOSTIC_H) toplev.h $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H)
+cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
+ output.h toplev.h $(FUNCTION_H) except.h $(TM_P_H) insn-config.h $(EXPR_H) \
+ $(CFGLAYOUT_H) $(CFGLOOP_H) $(OBSTACK_H) $(TARGET_H) $(TREE_H) \
+ tree-pass.h
cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(GGC_H) $(TM_P_H)
-cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
- function.h except.h $(GGC_H)
+ $(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(TM_P_H) \
+ $(TIMEVAR_H) $(OBSTACK_H) toplev.h
+cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h \
+ $(FUNCTION_H) except.h $(TIMEVAR_H) $(TREE_H)
cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(TIMEVAR_H) $(BASIC_BLOCK_H) hard-reg-set.h output.h flags.h \
- $(RECOG_H) toplev.h $(GGC_H) insn-config.h cselib.h $(TARGET_H) $(TM_P_H) \
- $(PARAMS_H)
+ $(RTL_H) $(TIMEVAR_H) hard-reg-set.h output.h $(FLAGS_H) $(RECOG_H) \
+ toplev.h insn-config.h cselib.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) \
+ $(REGS_H) $(EMIT_RTL_H) $(CFGLAYOUT_H) tree-pass.h $(CFGLOOP_H) $(EXPR_H)
cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) coretypes.h $(TM_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h flags.h
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(FLAGS_H) $(FUNCTION_H) \
+ $(OBSTACK_H) toplev.h $(TREE_FLOW_H) $(TREE_H)
cfgloopanal.o : cfgloopanal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h $(EXPR_H) coretypes.h $(TM_H)
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) \
+ $(OBSTACK_H) output.h
+struct-equiv.o : struct-equiv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) hard-reg-set.h output.h $(FLAGS_H) $(RECOG_H) \
+ insn-config.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) \
+ $(REGS_H) $(EMIT_RTL_H)
+loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
+ hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H) \
+ output.h intl.h $(DF_H) $(HASHTAB_H)
+loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h \
+ $(TM_H) $(TM_P_H) $(FUNCTION_H) $(FLAGS_H) $(DF_H) $(OBSTACK_H) output.h \
+ $(HASHTAB_H) except.h
cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h cfglayout.h output.h coretypes.h $(TM_H)
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) output.h \
+ coretypes.h $(TM_H) cfghooks.h $(OBSTACK_H)
loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h cfglayout.h \
- coretypes.h $(TM_H)
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) \
+ coretypes.h $(TM_H) $(OBSTACK_H) tree-pass.h $(TIMEVAR_H) $(FLAGS_H)
loop-unswitch.o : loop-unswitch.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h cfglayout.h $(PARAMS_H) \
- output.h $(EXPR_H) coretypes.h $(TM_H)
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
+ output.h $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H)
loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h cfglayout.h $(PARAMS_H) \
- output.h $(EXPR_H) coretypes.h $(TM_H)
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
+ output.h $(EXPR_H) coretypes.h $(TM_H) $(HASHTAB_H) $(RECOG_H) \
+ $(OBSTACK_H)
dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h
-et-forest.o : et-forest.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) et-forest.h alloc-pool.h
-combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- function.h insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
- $(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h $(TM_P_H) \
- $(TREE_H) $(TARGET_H) $(PARAMS_H)
+ hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) toplev.h $(TIMEVAR_H)
+et-forest.o : et-forest.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ et-forest.h alloc-pool.h $(BASIC_BLOCK_H)
+combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) $(FUNCTION_H) insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
+ rtlhooks-def.h $(BASIC_BLOCK_H) $(RECOG_H) $(REAL_H) hard-reg-set.h \
+ toplev.h $(TM_P_H) $(TREE_H) $(TARGET_H) output.h $(PARAMS_H) $(OPTABS_H) \
+ insn-codes.h $(TIMEVAR_H) tree-pass.h
regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- hard-reg-set.h flags.h $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(RECOG_H) reload.h \
- real.h toplev.h function.h output.h $(GGC_H) $(TM_P_H) $(EXPR_H) $(TIMEVAR_H)
-local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- flags.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
- output.h function.h $(INSN_ATTR_H) toplev.h except.h $(TM_P_H)
-bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) $(RTL_H) flags.h \
- $(BASIC_BLOCK_H) $(REGS_H) $(GGC_H)
- $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- reload.h function.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h \
- toplev.h $(TM_P_H)
-varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h $(GGC_H) errors.h
-ra.o : ra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TM_P_H) insn-config.h \
- $(RECOG_H) $(INTEGRATE_H) function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h \
- $(BASIC_BLOCK_H) df.h $(EXPR_H) output.h toplev.h flags.h reload.h ra.h
-ra-build.o : ra-build.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TM_P_H) \
- insn-config.h $(RECOG_H) function.h $(REGS_H) hard-reg-set.h \
- $(BASIC_BLOCK_H) df.h output.h $(GGC_H) ra.h gt-ra-build.h reload.h
-ra-colorize.o : ra-colorize.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TM_P_H) function.h $(REGS_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h output.h ra.h
-ra-debug.o : ra-debug.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- insn-config.h $(RECOG_H) function.h hard-reg-set.h $(BASIC_BLOCK_H) df.h output.h \
- ra.h $(TM_P_H)
-ra-rewrite.o : ra-rewrite.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TM_P_H) function.h $(REGS_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h $(EXPR_H) \
- output.h except.h ra.h reload.h insn-config.h
-reload.o : reload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h output.h \
- $(EXPR_H) $(OPTABS_H) reload.h $(RECOG_H) hard-reg-set.h insn-config.h \
- $(REGS_H) function.h real.h toplev.h $(TM_P_H) $(PARAMS_H)
-reload1.o : reload1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) real.h flags.h \
- $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) hard-reg-set.h insn-config.h \
- $(BASIC_BLOCK_H) $(RECOG_H) output.h function.h toplev.h $(TM_P_H) \
- except.h $(TREE_H)
-postreload.o : postreload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) real.h flags.h \
+ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(REGS_H) insn-config.h \
+ $(RECOG_H) reload.h $(REAL_H) toplev.h $(FUNCTION_H) output.h $(GGC_H) \
+ $(TM_P_H) $(EXPR_H) $(TIMEVAR_H) gt-regclass.h $(HASHTAB_H) \
+ $(TARGET_H)
+local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
+ output.h $(FUNCTION_H) $(INSN_ATTR_H) toplev.h except.h reload.h $(TM_P_H) \
+ $(GGC_H) $(INTEGRATE_H) $(TIMEVAR_H) tree-pass.h
+bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) $(GGC_H) gt-bitmap.h bitmap.h $(OBSTACK_H)
+global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) reload.h $(FUNCTION_H) $(RECOG_H) $(REGS_H) hard-reg-set.h \
+ insn-config.h output.h toplev.h $(TM_P_H) $(MACHMODE_H) tree-pass.h \
+ $(TIMEVAR_H) vecprim.h
+varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
+ $(HASHTAB_H) $(BCONFIG_H) $(VARRAY_H) toplev.h
+vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) coretypes.h vec.h $(GGC_H) \
+ toplev.h
+reload.o : reload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) output.h $(EXPR_H) $(OPTABS_H) reload.h $(RECOG_H) \
+ hard-reg-set.h insn-config.h $(REGS_H) $(FUNCTION_H) toplev.h \
+ addresses.h $(TM_P_H) $(PARAMS_H) $(TARGET_H) $(REAL_H)
+reload1.o : reload1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) hard-reg-set.h insn-config.h \
- $(BASIC_BLOCK_H) $(RECOG_H) output.h function.h toplev.h cselib.h $(TM_P_H) \
- except.h $(TREE_H)
+ $(BASIC_BLOCK_H) $(RECOG_H) output.h $(FUNCTION_H) toplev.h $(TM_P_H) \
+ addresses.h except.h $(TREE_H) $(REAL_H) $(FLAGS_H) $(MACHMODE_H) \
+ $(OBSTACK_H) $(TARGET_H)
+rtlhooks.o : rtlhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ rtlhooks-def.h $(EXPR_H) $(RECOG_H)
+postreload.o : postreload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(REAL_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \
+ hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \
+ $(FUNCTION_H) toplev.h cselib.h $(TM_P_H) except.h $(TREE_H) $(MACHMODE_H) \
+ $(OBSTACK_H) $(TIMEVAR_H) tree-pass.h
+postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
+ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
+ $(TM_P_H) except.h $(TREE_H) $(TARGET_H) $(HASHTAB_H) intl.h $(OBSTACK_H) \
+ $(PARAMS_H) $(TIMEVAR_H) tree-pass.h $(REAL_H)
caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- flags.h $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) function.h \
- $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H)
-bt-load.o : bt-load.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(BASIC_BLOCK_H) $(RTL_H) hard-reg-set.h $(REGS_H) $(OBSTACK_H) $(TM_P_H) \
- $(FIBHEAP_H) output.h $(TARGET_H) $(EXPR_H) flags.h $(INSN_ATTR_H)
-reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) conditions.h \
- hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(INSN_ATTR_H) except.h \
- $(RECOG_H) function.h flags.h output.h $(EXPR_H) toplev.h $(PARAMS_H) $(TM_P_H)
-alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
- hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h $(EXPR_H) \
- $(GGC_H) function.h cselib.h $(TREE_H) $(TM_P_H) langhooks.h $(TARGET_H) \
- gt-alias.h $(TIMEVAR_H) cgraph.h
-regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) insn-config.h \
- $(RECOG_H) output.h $(REGS_H) hard-reg-set.h flags.h function.h \
+ $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(FUNCTION_H) \
+ addresses.h $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H)
+bt-load.o : bt-load.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) except.h \
+ $(RTL_H) hard-reg-set.h $(REGS_H) $(TM_P_H) $(FIBHEAP_H) output.h $(EXPR_H) \
+ $(TARGET_H) $(FLAGS_H) $(INSN_ATTR_H) $(FUNCTION_H) tree-pass.h toplev.h
+reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ conditions.h hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) insn-config.h \
+ $(INSN_ATTR_H) except.h $(RECOG_H) $(FUNCTION_H) $(FLAGS_H) output.h \
+ $(EXPR_H) toplev.h $(PARAMS_H) $(TM_P_H) $(OBSTACK_H) $(RESOURCE_H) \
+ $(TIMEVAR_H) $(TARGET_H) tree-pass.h
+alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FLAGS_H) hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h \
+ $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
+ langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
+ $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) tree-pass.h
+regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ insn-config.h $(TIMEVAR_H) tree-pass.h \
+ $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
$(EXPR_H) $(BASIC_BLOCK_H) toplev.h $(TM_P_H) except.h reload.h
-haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- sched-int.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
- $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H)
-sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- sched-int.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
- $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h cselib.h $(PARAMS_H) $(TM_P_H)
-sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- sched-int.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
- $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H)
-sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- sched-int.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
- $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(PARAMS_H)
-sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- sched-int.h hard-reg-set.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(REGS_H) $(TM_P_H) \
- $(TARGET_H) real.h
-final.o : final.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h intl.h $(REGS_H) $(RECOG_H) conditions.h insn-config.h $(INSN_ATTR_H) \
- function.h real.h output.h hard-reg-set.h except.h debug.h xcoffout.h \
- toplev.h reload.h dwarf2out.h $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) \
- $(EXPR_H)
-recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) function.h \
- $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) hard-reg-set.h flags.h insn-config.h \
- $(INSN_ATTR_H) real.h toplev.h output.h reload.h $(TM_P_H)
-reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- $(RECOG_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h toplev.h reload.h \
- varray.h function.h $(TM_P_H) $(GGC_H) gt-reg-stack.h
+ddg.o : ddg.c $(DDG_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) \
+ toplev.h $(RTL_H) $(TM_P_H) $(REGS_H) $(FUNCTION_H) \
+ $(FLAGS_H) insn-config.h $(INSN_ATTR_H) except.h $(RECOG_H) \
+ $(SCHED_INT_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(EXPR_H) bitmap.h $(DF_H) \
+ hard-reg-set.h sbitmap.h $(TM_H)
+modulo-sched.o : modulo-sched.c $(DDG_H) $(CONFIG_H) $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(TARGET_H) toplev.h $(RTL_H) $(TM_P_H) $(REGS_H) $(FUNCTION_H) \
+ $(FLAGS_H) insn-config.h $(INSN_ATTR_H) except.h $(RECOG_H) \
+ $(SCHED_INT_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(EXPR_H) $(PARAMS_H) \
+ cfghooks.h $(DF_H) $(GCOV_IO_H) hard-reg-set.h $(TM_H) $(TIMEVAR_H) \
+ tree-pass.h
+haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
+ $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) \
+ $(TARGET_H) output.h $(PARAMS_H)
+sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
+ $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h cselib.h \
+ $(PARAMS_H) $(TM_P_H) $(DF_H)
+sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
+ $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(PARAMS_H) \
+ $(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) tree-pass.h
+sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
+ $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) \
+ $(PARAMS_H) $(CFGLAYOUT_H) $(TARGET_H) output.h
+sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(SCHED_INT_H) hard-reg-set.h $(BASIC_BLOCK_H) $(OBSTACK_H) \
+ $(TM_P_H) $(REAL_H) toplev.h tree-pass.h
+final.o : final.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) intl.h $(REGS_H) $(RECOG_H) conditions.h \
+ insn-config.h $(INSN_ATTR_H) $(FUNCTION_H) output.h hard-reg-set.h \
+ except.h debug.h xcoffout.h toplev.h reload.h dwarf2out.h tree-pass.h \
+ $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H) $(CFGLAYOUT_H) dbxout.h \
+ $(TIMEVAR_H) $(CGRAPH_H) $(COVERAGE_H) $(REAL_H)
+recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(FUNCTION_H) $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) \
+ $(FLAGS_H) insn-config.h $(INSN_ATTR_H) toplev.h output.h reload.h \
+ addresses.h $(TM_P_H) $(TIMEVAR_H) tree-pass.h hard-reg-set.h $(REAL_H)
+reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(TREE_H) $(RECOG_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
+ insn-config.h toplev.h reload.h $(FUNCTION_H) $(TM_P_H) $(GGC_H) \
+ $(BASIC_BLOCK_H) output.h $(VARRAY_H) $(TIMEVAR_H) tree-pass.h \
+ $(TARGET_H) vecprim.h
sreal.o: sreal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) sreal.h
-predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- flags.h insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h \
- $(RECOG_H) function.h except.h $(EXPR_H) $(TM_P_H) $(PREDICT_H) sreal.h \
- $(PARAMS_H) $(TARGET_H) cfgloop.h $(COVERAGE_H)
-lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(RTL_H) $(GGC_H)
+predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) \
+ hard-reg-set.h output.h toplev.h $(RECOG_H) $(FUNCTION_H) except.h \
+ $(TM_P_H) $(PREDICT_H) sreal.h $(PARAMS_H) $(TARGET_H) $(CFGLOOP_H) \
+ $(COVERAGE_H) $(SCEV_H) $(GGC_H) predict.def $(TIMEVAR_H) $(TREE_DUMP_H) \
+ $(TREE_FLOW_H) tree-pass.h $(EXPR_H)
+lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \
+ $(RTL_H) $(GGC_H) gt-lists.h
bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(BASIC_BLOCK_H) flags.h timevar.h output.h cfglayout.h $(FIBHEAP_H) \
- $(TARGET_H)
-tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h flags.h timevar.h \
- $(PARAMS_H) $(COVERAGE_H)
+ $(RTL_H) $(FLAGS_H) $(TIMEVAR_H) output.h $(CFGLAYOUT_H) $(FIBHEAP_H) \
+ $(TARGET_H) $(FUNCTION_H) $(TM_P_H) $(OBSTACK_H) $(EXPR_H) $(REGS_H) \
+ $(PARAMS_H) toplev.h tree-pass.h
+tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ $(TREE_H) $(BASIC_BLOCK_H) hard-reg-set.h output.h $(CFGLAYOUT_H) \
+ $(FLAGS_H) $(TIMEVAR_H) $(PARAMS_H) $(COVERAGE_H) $(FIBHEAP_H) \
+ tree-pass.h
cfglayout.o : cfglayout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(TREE_H) insn-config.h $(BASIC_BLOCK_H) hard-reg-set.h output.h \
- function.h cfglayout.h cfgloop.h $(TARGET_H) gt-cfglayout.h $(GGC_H)
-timevar.o : timevar.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TIMEVAR_H) flags.h \
- intl.h toplev.h
-regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h $(RECOG_H) function.h \
- resource.h $(OBSTACK_H) flags.h $(TM_P_H)
+ $(FUNCTION_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(TARGET_H) gt-cfglayout.h \
+ $(GGC_H) alloc-pool.h $(FLAGS_H) $(OBSTACK_H) tree-pass.h vecprim.h
+timevar.o : timevar.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TIMEVAR_H) $(FLAGS_H) intl.h toplev.h $(RTL_H) timevar.def
+regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
+ output.h $(RECOG_H) $(FUNCTION_H) $(OBSTACK_H) $(FLAGS_H) $(TM_P_H) \
+ addresses.h reload.h toplev.h $(TIMEVAR_H) tree-pass.h
ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(REGS_H) toplev.h flags.h insn-config.h function.h $(RECOG_H) $(TARGET_H) \
- $(BASIC_BLOCK_H) $(EXPR_H) output.h except.h $(TM_P_H) real.h $(OPTABS_H) \
- cfgloop.h
+ $(REGS_H) toplev.h $(FLAGS_H) insn-config.h $(FUNCTION_H) $(RECOG_H) \
+ $(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h except.h $(TM_P_H) \
+ $(REAL_H) $(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h $(TIMEVAR_H) tree-pass.h
+lambda-mat.o : lambda-mat.c $(LAMBDA_H) $(GGC_H) $(SYSTEM_H) $(CONFIG_H) \
+ $(TM_H) coretypes.h $(TREE_H)
+lambda-trans.o: lambda-trans.c $(LAMBDA_H) $(GGC_H) $(SYSTEM_H) $(CONFIG_H) \
+ $(TM_H) coretypes.h $(TARGET_H) $(TREE_H)
+lambda-code.o: lambda-code.c $(LAMBDA_H) $(GGC_H) $(SYSTEM_H) $(CONFIG_H) \
+ $(TM_H) $(OPTABS_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) \
+ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
+ $(TREE_DATA_REF_H) $(SCEV_H) $(EXPR_H) coretypes.h $(TARGET_H) \
+ tree-chrec.h tree-pass.h vec.h vecprim.h
params.o : params.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(PARAMS_H) toplev.h
+pointer-set.o: pointer-set.c pointer-set.h $(CONFIG_H) $(SYSTEM_H)
hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(HOOKS_H)
-pretty-print.o: $(CONFIG_H) $(SYSTEM_H) pretty-print.c $(PRETTY_PRINT_H)
+pretty-print.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h $(PRETTY_PRINT_H) \
+ $(TREE_H)
+errors.o : errors.c $(CONFIG_H) $(SYSTEM_H) errors.h $(BCONFIG_H)
-$(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) $(GGC_H) \
- $(RTL_H) $(REGS_H) hard-reg-set.h real.h insn-config.h conditions.h \
+$(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) \
+ $(RTL_H) $(REGS_H) hard-reg-set.h insn-config.h conditions.h \
output.h $(INSN_ATTR_H) $(SYSTEM_H) toplev.h $(TARGET_H) libfuncs.h \
- $(TARGET_DEF_H) function.h sched-int.h $(TM_P_H) $(EXPR_H) $(OPTABS_H) \
- langhooks.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(TARGET_DEF_H) $(FUNCTION_H) $(SCHED_INT_H) $(TM_P_H) $(EXPR_H) \
+ langhooks.h $(GGC_H) $(OPTABS_H) $(REAL_H) tm-constrs.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
$(out_file) $(OUTPUT_OPTION)
# Build auxiliary files that support ecoff format.
mips-tfile: mips-tfile.o version.o $(LIBDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tfile.o version.o $(LIBS)
-mips-tfile.o : mips-tfile.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h $(TM_H) version.h
+mips-tfile.o : mips-tfile.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) version.h $(srcdir)/../include/getopt.h gstab.h intl.h
mips-tdump: mips-tdump.o version.o $(LIBDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tdump.o version.o $(LIBS)
-mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h $(TM_H) version.h
+mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) version.h $(srcdir)/../include/getopt.h stab.def
# FIXME: writing proper dependencies for this is a *LOT* of work.
libbackend.o : $(OBJS-common:.o=.c) $(out_file) \
insn-config.h insn-flags.h insn-codes.h insn-constants.h \
- insn-attr.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ insn-attr.h $(DATESTAMP) $(BASEVER) $(DEVPHASE)
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_NAME=\"$(target_noncanonical)\" \
-DLOCALEDIR=\"$(localedir)\" \
- -c $(filter %.c,$^) -o $@
+ -c $(filter %.c,$^) -o $@ \
+ -DBASEVER=$(BASEVER_s) -DDATESTAMP=$(DATESTAMP_s) \
+ -DDEVPHASE=$(DEVPHASE_s) -combine
#
# Generate header and source files from the machine description,
@@ -1895,205 +2674,204 @@ libbackend.o : $(OBJS-common:.o=.c) $(out_file) \
.PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \
insn-emit.c insn-recog.c insn-extract.c insn-output.c insn-peep.c \
- insn-attr.h insn-attrtab.c
-
-# The following pair of rules has this effect:
-# genconfig is run only if the md has changed since genconfig was last run;
-# but the file insn-config.h is touched only when its contents actually change.
-
-# Each of the other insn-* files is handled by a similar pair of rules.
-
-# This causes an anomaly in the results of make -n
-# because insn-* is older than s-*
-# and thus make -n thinks that insn-* will be updated
-# and force recompilation of things that depend on it.
-# We use move-if-change precisely to avoid such recompilation.
-# But there is no way to teach make -n that it will be avoided.
-
-# Each of the insn-*.[ch] rules has a semicolon at the end,
-# for otherwise the system Make on SunOS 4.1 never tries
-# to recompile insn-*.o. To avoid problems and extra noise from
-# versions of make which don't like empty commands (nothing after the
-# trailing `;'), we call true for each.
-
-insn-config.h: s-config ; @true
-s-config : $(md_file) genconfig$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genconfig$(build_exeext) $(md_file) > tmp-config.h
- $(SHELL) $(srcdir)/move-if-change tmp-config.h insn-config.h
- $(STAMP) s-config
-
-insn-conditions.c: s-conditions ; @true
-s-conditions : $(md_file) genconditions$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genconditions$(build_exeext) $(md_file) > tmp-conditions.c
- $(SHELL) $(srcdir)/move-if-change tmp-conditions.c insn-conditions.c
- $(STAMP) s-conditions
+ insn-attr.h insn-attrtab.c insn-preds.c
-insn-conditions.o : insn-conditions.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(GTM_H) $(RTL_H) $(TM_P_H) $(REGS_H) function.h $(RECOG_H) real.h output.h \
- flags.h hard-reg-set.h resource.h toplev.h reload.h gensupport.h \
- insn-constants.h
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) insn-conditions.c
-
-dummy-conditions.o : dummy-conditions.c $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H) gensupport.h
-
-insn-flags.h: s-flags ; @true
-s-flags : $(md_file) genflags$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genflags$(build_exeext) $(md_file) > tmp-flags.h
- $(SHELL) $(srcdir)/move-if-change tmp-flags.h insn-flags.h
- $(STAMP) s-flags
-
-insn-codes.h: s-codes ; @true
-s-codes : $(md_file) gencodes$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./gencodes$(build_exeext) $(md_file) > tmp-codes.h
- $(SHELL) $(srcdir)/move-if-change tmp-codes.h insn-codes.h
- $(STAMP) s-codes
-
-insn-constants.h: s-constants ; @true
-s-constants : $(md_file) genconstants$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genconstants$(build_exeext) $(md_file) > tmp-constants.h
- $(SHELL) $(srcdir)/move-if-change tmp-constants.h insn-constants.h
- $(STAMP) s-constants
+# Dependencies for the md file. The first time through, we just assume
+# the md file itself and the generated dependency file (in order to get
+# it built). The second time through we have the dependency file.
+-include mddeps.mk
+MD_DEPS = s-mddeps $(md_file) $(MD_INCLUDES)
-insn-emit.o : insn-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(EXPR_H) real.h output.h insn-config.h $(OPTABS_H) reload.h \
- $(RECOG_H) toplev.h function.h flags.h hard-reg-set.h resource.h $(TM_P_H)
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-emit.c \
- $(OUTPUT_OPTION)
-
-insn-emit.c: s-emit ; @true
-s-emit : $(md_file) genemit$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genemit$(build_exeext) $(md_file) > tmp-emit.c
- $(SHELL) $(srcdir)/move-if-change tmp-emit.c insn-emit.c
- $(STAMP) s-emit
-
-insn-recog.o : insn-recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) insn-config.h $(RECOG_H) real.h output.h flags.h function.h \
- hard-reg-set.h resource.h $(TM_P_H) toplev.h reload.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-recog.c \
- $(OUTPUT_OPTION)
-
-insn-recog.c: s-recog ; @true
-s-recog : $(md_file) genrecog$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genrecog$(build_exeext) $(md_file) > tmp-recog.c
- $(SHELL) $(srcdir)/move-if-change tmp-recog.c insn-recog.c
- $(STAMP) s-recog
-
-insn-opinit.o : insn-opinit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) insn-config.h flags.h $(RECOG_H) $(EXPR_H) $(OPTABS_H) reload.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-opinit.c \
- $(OUTPUT_OPTION)
-
-insn-opinit.c: s-opinit ; @true
-s-opinit : $(md_file) genopinit$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genopinit$(build_exeext) $(md_file) > tmp-opinit.c
- $(SHELL) $(srcdir)/move-if-change tmp-opinit.c insn-opinit.c
- $(STAMP) s-opinit
-
-insn-extract.o : insn-extract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) toplev.h insn-config.h $(RECOG_H)
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-extract.c \
- $(OUTPUT_OPTION)
-
-insn-extract.c: s-extract ; @true
-s-extract : $(md_file) genextract$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genextract$(build_exeext) $(md_file) > tmp-extract.c
- $(SHELL) $(srcdir)/move-if-change tmp-extract.c insn-extract.c
- $(STAMP) s-extract
-
-insn-peep.o : insn-peep.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) output.h real.h insn-config.h $(RECOG_H) except.h \
- function.h $(TM_P_H)
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-peep.c \
- $(OUTPUT_OPTION)
-
-insn-peep.c: s-peep ; @true
-s-peep : $(md_file) genpeep$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genpeep$(build_exeext) $(md_file) > tmp-peep.c
- $(SHELL) $(srcdir)/move-if-change tmp-peep.c insn-peep.c
- $(STAMP) s-peep
-
-insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) real.h output.h $(INSN_ATTR_H) insn-config.h toplev.h \
- $(RECOG_H) $(TM_P_H) flags.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-attrtab.c \
- $(OUTPUT_OPTION)
-
-insn-attr.h: s-attr ; @true
-s-attr : $(md_file) genattr$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genattr$(build_exeext) $(md_file) > tmp-attr.h
- $(SHELL) $(srcdir)/move-if-change tmp-attr.h insn-attr.h
- $(STAMP) s-attr
-
-insn-attrtab.c: s-attrtab ; @true
-s-attrtab : $(md_file) genattrtab$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genattrtab$(build_exeext) $(md_file) > tmp-attrtab.c
- $(SHELL) $(srcdir)/move-if-change tmp-attrtab.c insn-attrtab.c
- $(STAMP) s-attrtab
-
-insn-output.o : insn-output.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(GGC_H) $(REGS_H) real.h conditions.h hard-reg-set.h \
- insn-config.h $(INSN_ATTR_H) $(EXPR_H) output.h $(RECOG_H) function.h \
- toplev.h flags.h insn-codes.h $(TM_P_H) $(TARGET_H)
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-output.c \
- $(OUTPUT_OPTION)
-
-insn-output.c: s-output ; @true
-s-output : $(md_file) genoutput$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genoutput$(build_exeext) $(md_file) > tmp-output.c
- $(SHELL) $(srcdir)/move-if-change tmp-output.c insn-output.c
- $(STAMP) s-output
-
-genrtl.o : genrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+s-mddeps: $(md_file) $(MD_INCLUDES) build/genmddeps$(build_exeext)
+ $(RUN_GEN) build/genmddeps$(build_exeext) $(md_file) > tmp-mddeps
+ $(SHELL) $(srcdir)/../move-if-change tmp-mddeps mddeps.mk
+ $(STAMP) s-mddeps
+
+# Header dependencies for generated source files.
+genrtl.o : genrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H)\
$(GGC_H)
-genrtl.c genrtl.h : s-genrtl
- @true # force gnu make to recheck modification times.
-
-s-genrtl: gengenrtl$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./gengenrtl$(build_exeext) -h > tmp-genrtl.h
- $(SHELL) $(srcdir)/move-if-change tmp-genrtl.h genrtl.h
- $(RUN_GEN) ./gengenrtl$(build_exeext) > tmp-genrtl.c
- $(SHELL) $(srcdir)/move-if-change tmp-genrtl.c genrtl.c
+insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(REGS_H) $(REAL_H) output.h $(INSN_ATTR_H) \
+ insn-config.h toplev.h $(RECOG_H) $(TM_P_H) $(FLAGS_H)
+insn-automata.o : insn-automata.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(REGS_H) $(REAL_H) output.h $(INSN_ATTR_H) \
+ insn-config.h toplev.h $(RECOG_H) $(TM_P_H) $(FLAGS_H)
+insn-emit.o : insn-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(EXPR_H) $(REAL_H) output.h insn-config.h $(OPTABS_H) \
+ reload.h $(RECOG_H) toplev.h $(FUNCTION_H) $(FLAGS_H) hard-reg-set.h \
+ $(RESOURCE_H) $(TM_P_H) $(BASIC_BLOCK_H) tm-constrs.h
+insn-extract.o : insn-extract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) toplev.h insn-config.h $(RECOG_H)
+insn-modes.o : insn-modes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(MACHMODE_H) $(REAL_H)
+insn-opinit.o : insn-opinit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) insn-config.h $(FLAGS_H) $(RECOG_H) $(EXPR_H) \
+ $(OPTABS_H) reload.h
+insn-output.o : insn-output.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(GGC_H) $(REGS_H) $(REAL_H) conditions.h \
+ hard-reg-set.h insn-config.h $(INSN_ATTR_H) $(EXPR_H) output.h \
+ $(RECOG_H) $(FUNCTION_H) toplev.h $(FLAGS_H) insn-codes.h $(TM_P_H) \
+ $(TARGET_H) tm-constrs.h
+insn-peep.o : insn-peep.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(RTL_H) $(REGS_H) output.h insn-config.h $(RECOG_H) except.h \
+ $(FUNCTION_H) $(TM_P_H) $(REAL_H) tm-constrs.h
+insn-preds.o : insn-preds.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(TREE_H) insn-config.h $(RECOG_H) output.h \
+ $(FLAGS_H) $(FUNCTION_H) hard-reg-set.h $(RESOURCE_H) $(TM_P_H) \
+ toplev.h reload.h $(REGS_H) $(REAL_H) tm-constrs.h
+insn-recog.o : insn-recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) insn-config.h $(RECOG_H) output.h $(FLAGS_H) \
+ $(FUNCTION_H) hard-reg-set.h $(RESOURCE_H) $(TM_P_H) toplev.h \
+ reload.h $(REAL_H) tm-constrs.h
+
+# For each of the files generated by running a generator program over
+# the machine description, the following pair of static pattern rules
+# runs the generator program only if the machine description has changed,
+# but touches the target file only when its contents actually change.
+# The "; @true" construct forces Make to recheck the timestamp on the
+# target file.
+
+simple_generated_h = insn-attr.h insn-codes.h insn-config.h insn-flags.h
+
+simple_generated_c = insn-attrtab.c insn-automata.c insn-emit.c \
+ insn-extract.c insn-opinit.c insn-output.c \
+ insn-peep.c insn-recog.c
+
+$(simple_generated_h): insn-%.h: s-%; @true
+
+$(simple_generated_h:insn-%.h=s-%): s-%: build/gen%$(build_exeext) \
+ $(MD_DEPS) insn-conditions.md
+ $(RUN_GEN) build/gen$*$(build_exeext) $(md_file) \
+ insn-conditions.md > tmp-$*.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-$*.h insn-$*.h
+ $(STAMP) s-$*
+
+$(simple_generated_c): insn-%.c: s-%; @true
+$(simple_generated_c:insn-%.c=s-%): s-%: build/gen%$(build_exeext) \
+ $(MD_DEPS) insn-conditions.md
+ $(RUN_GEN) build/gen$*$(build_exeext) $(md_file) \
+ insn-conditions.md > tmp-$*.c
+ $(SHELL) $(srcdir)/../move-if-change tmp-$*.c insn-$*.c
+ $(STAMP) s-$*
+
+# genconstants needs to run before insn-conditions.md is available
+# (because the constants may be used in the conditions).
+insn-constants.h: s-constants; @true
+s-constants: build/genconstants$(build_exeext) $(MD_DEPS)
+ $(RUN_GEN) build/genconstants$(build_exeext) $(md_file) \
+ > tmp-constants.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-constants.h insn-constants.h
+ $(STAMP) s-constants
+
+# gencheck doesn't read the machine description, and the file produced
+# doesn't use the insn-* convention.
+tree-check.h: s-check ; @true
+s-check : build/gencheck$(build_exeext)
+ $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
+ $(STAMP) s-check
+
+# gencondmd doesn't use the standard naming convention.
+build/gencondmd.c: s-conditions; @true
+s-conditions: $(MD_DEPS) build/genconditions$(build_exeext)
+ $(RUN_GEN) build/genconditions$(build_exeext) $(md_file) > tmp-condmd.c
+ $(SHELL) $(srcdir)/../move-if-change tmp-condmd.c build/gencondmd.c
+ $(STAMP) s-conditions
+
+insn-conditions.md: s-condmd; @true
+s-condmd: build/gencondmd$(build_exeext)
+ $(RUN_GEN) build/gencondmd$(build_exeext) > tmp-cond.md
+ $(SHELL) $(srcdir)/../move-if-change tmp-cond.md insn-conditions.md
+ $(STAMP) s-condmd
+
+
+# These files are generated by running the same generator more than
+# once with different options, so they have custom rules. The
+# stampfile idiom is the same.
+genrtl.c: s-genrtl; @true
+genrtl.h: s-genrtl-h; @true
+
+s-genrtl: build/gengenrtl$(build_exeext)
+ $(RUN_GEN) build/gengenrtl$(build_exeext) > tmp-genrtl.c
+ $(SHELL) $(srcdir)/../move-if-change tmp-genrtl.c genrtl.c
$(STAMP) s-genrtl
-insn-modes.o : insn-modes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(MACHMODE_H) real.h
-min-insn-modes.c insn-modes.c insn-modes.h : s-modes ; @true
-
-s-modes: genmodes$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genmodes$(build_exeext) -h > tmp-modes.h
- $(SHELL) $(srcdir)/move-if-change tmp-modes.h insn-modes.h
- $(RUN_GEN) ./genmodes$(build_exeext) -m > tmp-min-modes.c
- $(SHELL) $(srcdir)/move-if-change tmp-min-modes.c min-insn-modes.c
- $(RUN_GEN) ./genmodes$(build_exeext) > tmp-modes.c
- $(SHELL) $(srcdir)/move-if-change tmp-modes.c insn-modes.c
+s-genrtl-h: build/gengenrtl$(build_exeext)
+ $(RUN_GEN) build/gengenrtl$(build_exeext) -h > tmp-genrtl.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-genrtl.h genrtl.h
+ $(STAMP) s-genrtl-h
+
+insn-modes.c: s-modes; @true
+insn-modes.h: s-modes-h; @true
+min-insn-modes.c: s-modes-m; @true
+
+s-modes: build/genmodes$(build_exeext)
+ $(RUN_GEN) build/genmodes$(build_exeext) > tmp-modes.c
+ $(SHELL) $(srcdir)/../move-if-change tmp-modes.c insn-modes.c
$(STAMP) s-modes
-tm-preds.h: s-preds; @true
+s-modes-h: build/genmodes$(build_exeext)
+ $(RUN_GEN) build/genmodes$(build_exeext) -h > tmp-modes.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-modes.h insn-modes.h
+ $(STAMP) s-modes-h
+
+s-modes-m: build/genmodes$(build_exeext)
+ $(RUN_GEN) build/genmodes$(build_exeext) -m > tmp-min-modes.c
+ $(SHELL) $(srcdir)/../move-if-change tmp-min-modes.c min-insn-modes.c
+ $(STAMP) s-modes-m
-s-preds: genpreds$(build_exeext) $(srcdir)/move-if-change
- $(RUN_GEN) ./genpreds$(build_exeext) > tmp-preds.h
- $(SHELL) $(srcdir)/move-if-change tmp-preds.h tm-preds.h
+insn-preds.c: s-preds; @true
+tm-preds.h: s-preds-h; @true
+tm-constrs.h: s-constrs-h; @true
+
+s-preds: $(MD_DEPS) build/genpreds$(build_exeext)
+ $(RUN_GEN) build/genpreds$(build_exeext) $(md_file) > tmp-preds.c
+ $(SHELL) $(srcdir)/../move-if-change tmp-preds.c insn-preds.c
$(STAMP) s-preds
-GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h $(srcdir)/cpplib.h \
- $(host_xm_file_list) $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) \
- $(srcdir)/bitmap.h $(srcdir)/coverage.c $(srcdir)/function.h $(srcdir)/rtl.h \
- $(srcdir)/optabs.h $(srcdir)/tree.h $(srcdir)/libfuncs.h $(srcdir)/hashtable.h \
- $(srcdir)/real.h $(srcdir)/varray.h $(srcdir)/insn-addr.h \
+s-preds-h: $(MD_DEPS) build/genpreds$(build_exeext)
+ $(RUN_GEN) build/genpreds$(build_exeext) -h $(md_file) > tmp-preds.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-preds.h tm-preds.h
+ $(STAMP) s-preds-h
+
+s-constrs-h: $(MD_DEPS) build/genpreds$(build_exeext)
+ $(RUN_GEN) build/genpreds$(build_exeext) -c $(md_file) > tmp-constrs.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-constrs.h tm-constrs.h
+ $(STAMP) s-constrs-h
+
+GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \
+ $(CPP_ID_DATA_H) $(host_xm_file_list) \
+ $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) $(srcdir)/bitmap.h \
+ $(srcdir)/coverage.c $(srcdir)/rtl.h \
+ $(srcdir)/optabs.h $(srcdir)/tree.h $(srcdir)/function.h $(srcdir)/libfuncs.h $(SYMTAB_H) \
+ $(srcdir)/real.h $(srcdir)/varray.h $(srcdir)/insn-addr.h $(srcdir)/hwint.h \
+ $(srcdir)/ipa-reference.h $(srcdir)/output.h \
$(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/cgraph.h \
- $(srcdir)/c-common.h $(srcdir)/c-tree.h \
+ $(srcdir)/c-common.h $(srcdir)/c-tree.h $(srcdir)/reload.h \
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
+ $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-inline.c \
$(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \
- $(srcdir)/dojump.c \
+ $(srcdir)/dojump.c $(srcdir)/tree-profile.c \
$(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
- $(srcdir)/fold-const.c $(srcdir)/function.c \
+ $(srcdir)/function.c $(srcdir)/except.h \
$(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
- $(srcdir)/profile.c $(srcdir)/ra-build.c $(srcdir)/regclass.c \
- $(srcdir)/reg-stack.c $(srcdir)/cfglayout.c $(srcdir)/langhooks.c \
- $(srcdir)/sdbout.c $(srcdir)/stmt.c $(srcdir)/stor-layout.c \
+ $(srcdir)/profile.c $(srcdir)/regclass.c \
+ $(srcdir)/reg-stack.c $(srcdir)/cfglayout.c \
+ $(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
$(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
- $(out_file) \
+ $(srcdir)/tree-mudflap.c $(srcdir)/tree-flow.h \
+ $(srcdir)/c-objc-common.c $(srcdir)/c-common.c $(srcdir)/c-parser.c \
+ $(srcdir)/tree-ssanames.c $(srcdir)/tree-eh.c $(srcdir)/tree-ssa-address.c \
+ $(srcdir)/tree-phinodes.c $(srcdir)/tree-cfg.c \
+ $(srcdir)/tree-dfa.c $(srcdir)/tree-ssa-propagate.c \
+ $(srcdir)/tree-iterator.c $(srcdir)/gimplify.c \
+ $(srcdir)/tree-chrec.h $(srcdir)/tree-vect-generic.c \
+ $(srcdir)/tree-ssa-operands.h $(srcdir)/tree-ssa-operands.c \
+ $(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \
+ $(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
+ $(srcdir)/tree-ssa-structalias.c \
+ $(srcdir)/c-pragma.h $(srcdir)/omp-low.c \
+ $(srcdir)/targhooks.c $(srcdir)/cgraphunit.c $(out_file) \
@all_gtfiles@
GTFILES_FILES_LANGS = @all_gtfiles_files_langs@
@@ -2101,241 +2879,182 @@ GTFILES_FILES_FILES = @all_gtfiles_files_files@
GTFILES_LANG_DIR_NAMES = @subdirs@
GTFILES_SRCDIR = @srcdir@
+GTFILES_FILES_FILES_C = $(subst $(srcdir)/,, \
+ $(filter %.c, $(GTFILES_FILES_FILES)))
+GTFILES_FILES_FILES_H = $(addprefix gt-, \
+ $(subst /,-,$(GTFILES_FILES_FILES_C:.c=.h)))
+GTFILES_LANG_DIR_NAMES_H = $(foreach d,$(GTFILES_LANG_DIR_NAMES), gtype-$(d).h)
+ALL_GTFILES_H := $(sort $(GTFILES_FILES_FILES_H) $(GTFILES_LANG_DIR_NAMES_H))
+
+$(ALL_GTFILES_H) : s-gtype ; @true
+
+
gt-cgraph.h gt-coverage.h gtype-desc.h gtype-desc.c gt-except.h \
-gt-function.h gt-integrate.h gt-stmt.h gt-tree.h gt-varasm.h \
+gt-function.h gt-integrate.h gt-tree.h gt-varasm.h \
gt-emit-rtl.h gt-explow.h gt-stor-layout.h gt-regclass.h \
-gt-lists.h gt-alias.h gt-cselib.h gt-fold-const.h gt-gcse.h \
+gt-lists.h gt-alias.h gt-cselib.h gt-gcse.h \
gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dojump.h \
-gt-dwarf2out.h gt-ra-build.h gt-reg-stack.h gt-dwarf2asm.h \
-gt-dbxout.h gt-c-common.h gt-c-decl.h gt-c-parse.h \
-gt-c-pragma.h gtype-c.h gt-input.h gt-cfglayout.h \
-gt-stringpool.h gt-langhooks.h : s-gtype ; @true
-
-gtyp-gen.h: Makefile
+gt-dwarf2out.h gt-dwarf2asm.h \
+gt-dbxout.h \
+gtype-c.h gt-cfglayout.h \
+gt-tree-mudflap.h gt-tree-vect-generic.h \
+gt-tree-profile.h gt-tree-ssa-address.h \
+gt-tree-ssanames.h gt-tree-iterator.h gt-gimplify.h \
+gt-tree-phinodes.h gt-tree-nested.h \
+gt-tree-ssa-operands.h gt-tree-ssa-propagate.h \
+gt-tree-ssa-structalias.h gt-ipa-inline.h gt-cgraphunit.h \
+gt-stringpool.h gt-targhooks.h gt-omp-low.h : s-gtype ; @true
+
+define echo_quoted_to_gtyp
+ echo "\"$(gtyp)\", " >> tmp-gtyp.h
+
+endef
+
+gtyp-gen.h: s-gtyp-gen ; @true
+s-gtyp-gen: Makefile
echo "/* This file is machine generated. Do not edit. */" > tmp-gtyp.h
echo "static const char *const srcdir = " >> tmp-gtyp.h
echo "\"$(GTFILES_SRCDIR)\"" >> tmp-gtyp.h
echo ";" >> tmp-gtyp.h
echo "static const char *const lang_files[] = {" >> tmp-gtyp.h
- ll="$(GTFILES_FILES_FILES)"; \
- for f in $$ll; do \
- echo "\"$$f\", "; done >> tmp-gtyp.h
+ $(foreach gtyp,$(GTFILES_FILES_FILES),$(echo_quoted_to_gtyp))
echo "NULL};" >> tmp-gtyp.h
echo "static const char *const langs_for_lang_files[] = {" >> tmp-gtyp.h
- ff="$(GTFILES_FILES_LANGS)"; \
- for f in $$ff; do \
- echo "\"$$f\", " ; done >> tmp-gtyp.h
+ $(foreach gtyp,$(GTFILES_FILES_LANGS),$(echo_quoted_to_gtyp))
echo "NULL};" >> tmp-gtyp.h
echo "static const char *const all_files[] = {" >> tmp-gtyp.h
- gf="$(GTFILES)"; \
- for f in $$gf; do \
- echo "\"$$f\", "; done >> tmp-gtyp.h
+ $(foreach gtyp,$(GTFILES),$(echo_quoted_to_gtyp))
echo " NULL};" >> tmp-gtyp.h
echo "static const char *const lang_dir_names[] = { \"c\", " >> tmp-gtyp.h
- gf="$(GTFILES_LANG_DIR_NAMES)"; \
- for l in $$gf; do \
- echo "\"$$l\", "; done >> tmp-gtyp.h
+ $(foreach gtyp,$(GTFILES_LANG_DIR_NAMES),$(echo_quoted_to_gtyp))
echo "NULL};" >> tmp-gtyp.h
- $(SHELL) $(srcdir)/move-if-change tmp-gtyp.h gtyp-gen.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-gtyp.h gtyp-gen.h
+ $(STAMP) s-gtyp-gen
-s-gtype: gengtype$(build_exeext) $(GTFILES)
- $(RUN_GEN) ./gengtype
+s-gtype: build/gengtype$(build_exeext) $(GTFILES)
+ $(RUN_GEN) build/gengtype$(build_exeext)
$(STAMP) s-gtype
#
-# Compile the programs that generate insn-* from the machine description.
-# They are compiled with $(CC_FOR_BUILD), and associated libraries,
-# since they need to run on this machine
-# even if GCC is being compiled to run on some other machine.
-
-# $(CONFIG_H) is omitted from the deps of the gen*.o
-# because these programs don't really depend on anything
-# about the target machine. They do depend on config.h itself,
-# since that describes the host machine.
-
-# The names of programs that run on the "build" machine.
-genprognames=genconfig genflags gencodes genemit genopinit genrecog \
- genextract genpeep genattr genoutput
-
-# The names of the executable files for those programs.
-genprogs=$(genprognames:%=%$(build_exeext))
-
-# Object files used in those programs.
-genobjs=$(genprognames:%=%.o) read-rtl.o gensupport.o genattrtab.o \
- genautomata.o gengenrtl.o genmodes.o genpreds.o gengtype.o \
- genconstants.o gen-protos.o scan.o fix-header.o scan-decls.o \
- gencheck.o dummy-conditions.o genconditions.o
-
-$(genprogs): %$(build_exeext): %.o $(BUILD_RTL) $(BUILD_SUPPORT) \
- $(BUILD_PRINT) $(BUILD_ERRORS) \
- $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- $< $(BUILD_RTL) $(BUILD_SUPPORT) $(BUILD_PRINT) \
- $(BUILD_ERRORS) $(BUILD_LIBS)
+# How to compile object files to run on the build machine.
-$(genobjs): %.o : %.c
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+build/%.o : # dependencies provided by explicit rule later
+ $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -o $@ $<
-read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) $(RTL_H) \
- $(OBSTACK_H) $(HASHTAB_H)
-
-gensupport.o: gensupport.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) $(RTL_H) \
- $(OBSTACK_H) errors.h $(HASHTAB_H) gensupport.h
-
-genconfig.o : genconfig.c $(RTL_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h
-
-genflags.o : genflags.c $(RTL_H) $(OBSTACK_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h
-
-gencodes.o : gencodes.c $(RTL_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h
-
-genconstants$(build_exeext) : genconstants.o $(BUILD_RTL) $(BUILD_EARLY_SUPPORT) \
- $(BUILD_ERRORS) $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- genconstants.o $(BUILD_EARLY_SUPPORT) $(BUILD_RTL) \
- $(BUILD_ERRORS) $(BUILD_LIBS)
-
-genconstants.o : genconstants.c $(RTL_H) $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) \
- errors.h
-
-genemit.o : genemit.c $(RTL_H) $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) \
- errors.h gensupport.h
-
-genopinit.o : genopinit.c $(RTL_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h
-
-genrecog.o : genrecog.c $(RTL_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h
-
-genextract.o : genextract.c $(RTL_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) insn-config.h errors.h gensupport.h
-
-genpeep.o : genpeep.c $(RTL_H) $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) \
- errors.h gensupport.h
-
-genattr.o : genattr.c $(RTL_H) $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h \
+# Header dependencies for the programs that generate source code.
+# These are library modules...
+build/errors.o : errors.c $(BCONFIG_H) $(SYSTEM_H) errors.h
+build/gensupport.o: gensupport.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) errors.h $(HASHTAB_H) \
gensupport.h
-
-genattrtab$(build_exeext) : genattrtab.o genautomata.o \
- $(BUILD_RTL) $(BUILD_SUPPORT) $(BUILD_PRINT) $(BUILD_ERRORS) $(BUILD_VARRAY) \
- $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- genattrtab.o genautomata.o \
- $(BUILD_RTL) $(BUILD_SUPPORT) $(BUILD_PRINT) $(BUILD_ERRORS) \
- $(BUILD_VARRAY) $(BUILD_LIBS) -lm
-
-genattrtab.o : genattrtab.c $(RTL_H) $(OBSTACK_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(GGC_H) gensupport.h genattrtab.h
-
-genautomata.o : genautomata.c $(RTL_H) $(OBSTACK_H) $(BCONFIG_H) \
- $(SYSTEM_H) coretypes.h $(GTM_H) errors.h varray.h genattrtab.h $(HASHTAB_H)
-
-genoutput.o : genoutput.c $(RTL_H) $(BCONFIG_H) \
+build/ggc-none.o : ggc-none.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(GGC_H)
+build/min-insn-modes.o : min-insn-modes.c $(BCONFIG_H) $(SYSTEM_H) \
+ $(MACHMODE_H)
+build/print-rtl.o: print-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(GTM_H) $(RTL_BASE_H)
+build/read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) $(HASHTAB_H) gensupport.h
+build/rtl.o: rtl.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) \
+ $(RTL_H) $(REAL_H) $(GGC_H) errors.h
+build/vec.o : vec.c $(BCONFIG_H) $(SYSTEM_H) $(TREE_H) coretypes.h vec.h \
+ $(GGC_H) toplev.h
+build/gencondmd.o : build/gencondmd.c $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) insn-constants.h $(RTL_H) $(TM_P_H) \
+ $(FUNCTION_H) $(REGS_H) $(RECOG_H) $(REAL_H) output.h $(FLAGS_H) \
+ $(RESOURCE_H) toplev.h reload.h except.h tm-constrs.h
+# This pulls in tm-pred.h which contains inline functions wrapping up
+# predicates from the back-end so those functions must be discarded.
+# No big deal since gencondmd.c is a dummy file for non-GCC compilers.
+build/gencondmd.o : \
+ BUILD_CFLAGS := $(filter-out -fkeep-inline-functions, $(BUILD_CFLAGS))
+
+# ...these are the programs themselves.
+build/genattr.o : genattr.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h
+build/genattrtab.o : genattrtab.c $(RTL_BASE_H) $(OBSTACK_H) \
+ $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(GGC_H) \
+ gensupport.h
+build/genautomata.o : genautomata.c $(RTL_BASE_H) $(OBSTACK_H) \
+ $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h vec.h \
+ $(HASHTAB_H) gensupport.h
+build/gencheck.o : gencheck.c gencheck.h tree.def $(BCONFIG_H) $(GTM_H) \
+ $(SYSTEM_H) coretypes.h $(lang_tree_files)
+build/genchecksum.o : genchecksum.c $(BCONFIG_H) $(SYSTEM_H) $(MD5_H)
+build/gencodes.o : gencodes.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h
+build/genconditions.o : genconditions.c $(RTL_BASE_H) $(BCONFIG_H) \
+ $(SYSTEM_H) coretypes.h $(GTM_H) errors.h
+build/genconfig.o : genconfig.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h
+build/genconstants.o : genconstants.c $(RTL_BASE_H) $(BCONFIG_H) \
+ $(SYSTEM_H) coretypes.h $(GTM_H) errors.h
+build/genemit.o : genemit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h
+build/genextract.o : genextract.c $(RTL_BASE_H) $(BCONFIG_H) \
+ $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h vecprim.h
+build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H) \
$(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h
+build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def
+build/gengtype-lex.o : gengtype-lex.c gengtype.h gengtype-yacc.h \
+ $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) vec.h
+build/gengtype-yacc.o : gengtype-yacc.c gengtype.h $(BCONFIG_H) \
+ $(SYSTEM_H) coretypes.h $(GTM_H)
+build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(GTM_H) gengtype.h gtyp-gen.h rtl.def insn-notes.def errors.h
+build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(GTM_H) $(RTL_BASE_H) errors.h gensupport.h
+build/genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h \
+ $(HASHTAB_H) machmode.def $(extra_modes_file)
+build/genopinit.o : genopinit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h
+build/genoutput.o : genoutput.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h
+build/genpeep.o : genpeep.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h toplev.h
+build/genpreds.o : genpreds.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h $(OBSTACK_H)
+build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ coretypes.h $(GTM_H) errors.h gensupport.h
-gengenrtl$(build_exeext) : gengenrtl.o $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- gengenrtl.o $(BUILD_LIBS)
-
-gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def
-
-genmodes$(build_exeext) : genmodes.o $(BUILD_ERRORS) $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- genmodes.o $(BUILD_ERRORS) $(BUILD_LIBS)
-
-genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h $(HASHTAB_H) \
- machmode.def $(extra_modes_file)
-
-genpreds$(build_exeext) : genpreds.o $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- genpreds.o $(BUILD_LIBS)
-
-genpreds.o : genpreds.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H)
+# Compile the programs that generate insn-* from the machine description.
+# They are compiled with $(CC_FOR_BUILD), and associated libraries,
+# since they need to run on this machine
+# even if GCC is being compiled to run on some other machine.
-gengtype$(build_exeext) : gengtype.o gengtype-lex.o gengtype-yacc.o \
- $(BUILD_LIBDEPS)
+# As a general rule...
+build/gen%$(build_exeext): build/gen%.o $(BUILD_LIBDEPS)
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- gengtype.o gengtype-lex.o gengtype-yacc.o $(BUILD_LIBS)
+ $(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
-gengtype.o : gengtype.c gengtype.h $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) \
- real.h $(RTL_BASE_H) gtyp-gen.h
+# All these programs use the MD reader ($(BUILD_RTL)).
+genprogmd = attr attrtab automata codes conditions config constants emit \
+ extract flags mddeps opinit output peep preds recog
+$(genprogmd:%=build/gen%$(build_exeext)): $(BUILD_RTL) $(BUILD_ERRORS)
-gengtype-lex.o : gengtype-lex.c gengtype.h gengtype-yacc.h \
- $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H)
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) \
- $< $(OUTPUT_OPTION)
+# These programs need libs over and above what they get from the above list.
+build/genautomata$(build_exeext) : BUILD_LIBS += -lm
-gengtype-yacc.o : gengtype-yacc.c gengtype.h $(BCONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GTM_H)
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) \
- $< $(OUTPUT_OPTION)
+# These programs are not linked with the MD reader.
+build/gengenrtl$(build_exeext) : $(BUILD_ERRORS)
+build/genmodes$(build_exeext) : $(BUILD_ERRORS)
+build/gengtype$(build_exeext) : build/gengtype-lex.o \
+ build/gengtype-yacc.o $(BUILD_ERRORS)
+# Generated source files for gengtype.
gengtype-lex.c : gengtype-lex.l
-$(FLEX) $(FLEXFLAGS) -o$@ $<
-
-gengtype-yacc.c gengtype-yacc.h: gengtype-yacc.y
- -$(BISON) $(BISONFLAGS) -d -o gengtype-yacc.c $<
-
-genconditions$(build_exeext) : genconditions.o $(BUILD_EARLY_SUPPORT) \
- $(BUILD_RTL) $(BUILD_ERRORS) $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
- genconditions.o $(BUILD_EARLY_SUPPORT) $(BUILD_RTL) \
- $(BUILD_ERRORS) $(BUILD_LIBS)
-
-genconditions.o : genconditions.c $(RTL_H) $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
- $(GTM_H) errors.h
-
-#
-# Compile the libraries to be used by gen*.
-# If we are not cross-building, gen* use the same .o's that cc1 will use,
-# and BUILD_PREFIX_1 is `loser-', just to ensure these rules don't conflict
-# with the rules for rtl.o, etc.
-$(BUILD_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) $(RTL_H) \
- real.h $(GGC_H) errors.h
- rm -f $(BUILD_PREFIX)rtl.c
- sed -e 's/config[.]h/bconfig.h/' $(srcdir)/rtl.c > $(BUILD_PREFIX)rtl.c
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)rtl.c $(OUTPUT_OPTION)
-
-print-rtl1.o: $(srcdir)/print-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
- $(GTM_H) $(RTL_H) $(TREE_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H)
- rm -f print-rtl1.c
- sed -e 's/config[.]h/bconfig.h/' $(srcdir)/print-rtl.c > print-rtl1.c
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) print-rtl1.c $(OUTPUT_OPTION)
-
-$(BUILD_PREFIX_1)bitmap.o: $(srcdir)/bitmap.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) \
- $(RTL_H) flags.h $(BASIC_BLOCK_H) $(REGS_H) $(GGC_H)
- rm -f $(BUILD_PREFIX)bitmap.c
- sed -e 's/config[.]h/bconfig.h/' $(srcdir)/bitmap.c > $(BUILD_PREFIX)bitmap.c
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)bitmap.c $(OUTPUT_OPTION)
-
-$(BUILD_PREFIX_1)errors.o: errors.c $(BCONFIG_H) $(SYSTEM_H) errors.h
- rm -f $(BUILD_PREFIX)errors.c
- sed -e 's/config[.]h/bconfig.h/' $(srcdir)/errors.c > $(BUILD_PREFIX)errors.c
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)errors.c $(OUTPUT_OPTION)
-
-$(BUILD_PREFIX_1)varray.o: varray.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) varray.h \
- $(RTL_H) $(GGC_H) $(TREE_H) bitmap.h errors.h
- rm -f $(BUILD_PREFIX)varray.c
- sed -e 's/config[.]h/bconfig.h/' $(srcdir)/varray.c > \
- $(BUILD_PREFIX)varray.c
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) \
- $(BUILD_PREFIX)varray.c $(OUTPUT_OPTION)
-
-$(BUILD_PREFIX_1)ggc-none.o: ggc-none.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) $(GGC_H)
- rm -f $(BUILD_PREFIX)ggc-none.c
- sed -e 's/config[.]h/bconfig.h/' $(srcdir)/ggc-none.c > $(BUILD_PREFIX)ggc-none.c
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)ggc-none.c $(OUTPUT_OPTION)
-
-min-insn-modes.o: min-insn-modes.c $(BCONFIG_H) $(SYSTEM_H) $(MACHMODE_H)
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) \
- min-insn-modes.c $(OUTPUT_OPTION)
+# This is a pattern rule solely so that Make knows it need not run the
+# command twice. The modifier to $@ ensures that Bison is asked to
+# produce a .c file, whether or not Make decides it needs the .h file
+# first.
+gengtype-y%.c gengtype-y%.h: gengtype-y%.y
+ -$(BISON) $(BISONFLAGS) -d -o $(@:.h=.c) $<
#
# Remake internationalization support.
intl.o: intl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h Makefile
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
-DLOCALEDIR=\"$(localedir)\" \
-c $(srcdir)/intl.c $(OUTPUT_OPTION)
@@ -2352,48 +3071,18 @@ PREPROCESSOR_DEFINES = \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
@TARGET_SYSTEM_ROOT_DEFINE@
-LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \
- cpphash.o cpperror.o cppinit.o cppcharset.o \
- hashtable.o line-map.o mkdeps.o cpppch.o
-
-LIBCPP_DEPS = $(CPPLIB_H) cpphash.h line-map.h hashtable.h intl.h \
- $(OBSTACK_H) $(CONFIG_H) $(SYSTEM_H)
-
-# Most of the other archives built/used by this makefile are for
-# targets. This one is strictly for the host.
-libcpp.a: $(LIBCPP_OBJS)
- -rm -rf libcpp.a
- $(AR) $(AR_FLAGS) libcpp.a $(LIBCPP_OBJS)
- -$(RANLIB) libcpp.a
-
-cppcharset.o: cppcharset.c $(LIBCPP_DEPS) cppucnid.h
-cpperror.o: cpperror.c $(LIBCPP_DEPS)
-cppexp.o: cppexp.c $(LIBCPP_DEPS)
-cpplex.o: cpplex.c $(LIBCPP_DEPS)
-cppmacro.o: cppmacro.c $(LIBCPP_DEPS)
-cpplib.o: cpplib.c $(LIBCPP_DEPS)
-cpphash.o: cpphash.c $(LIBCPP_DEPS)
-cpptrad.o: cpptrad.c $(LIBCPP_DEPS)
-cppfiles.o: cppfiles.c $(LIBCPP_DEPS) $(HASHTAB_H) mkdeps.h
-cppinit.o: cppinit.c $(LIBCPP_DEPS) mkdeps.h
-cpppch.o: cpppch.c $(LIBCPP_DEPS) mkdeps.h
-
cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
cppdefault.h Makefile
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
$(PREPROCESSOR_DEFINES) \
-c $(srcdir)/cppdefault.c $(OUTPUT_OPTION)
-mkdeps.o: mkdeps.c $(CONFIG_H) $(SYSTEM_H) mkdeps.h
-hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H)
-line-map.o: line-map.c line-map.h intl.h $(CONFIG_H) $(SYSTEM_H)
-
# Note for the stamp targets, we run the program `true' instead of
# having an empty command (nothing following the semicolon).
proto: config.status protoize$(exeext) unprotoize$(exeext) SYSCALLS.c.X
-PROTO_OBJS = intl.o version.o cppdefault.o
+PROTO_OBJS = intl.o version.o cppdefault.o errors.o
protoize$(exeext): protoize.o $(PROTO_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ protoize.o $(PROTO_OBJS) $(LIBS)
@@ -2402,18 +3091,18 @@ unprotoize$(exeext): unprotoize.o $(PROTO_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ unprotoize.o $(PROTO_OBJS) $(LIBS)
protoize.o: protoize.c $(srcdir)/../include/getopt.h $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) Makefile version.h
+ coretypes.h $(TM_H) Makefile version.h cppdefault.h intl.h
(SHLIB_LINK='$(SHLIB_LINK)' \
SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
$(srcdir)/protoize.c $(OUTPUT_OPTION))
-unprotoize.o: protoize.c $(srcdir)/../include/getopt.h \
- $(CONFIG_H) $(SYSTEM_H) Makefile version.h
+unprotoize.o: protoize.c $(srcdir)/../include/getopt.h $(CONFIG_H) \
+ $(SYSTEM_H) coretypes.h $(TM_H) Makefile version.h cppdefault.h intl.h
(SHLIB_LINK='$(SHLIB_LINK)' \
SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
- $(CC) -c -DUNPROTOIZE $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(CC) -c -DUNPROTOIZE $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
$(srcdir)/protoize.c $(OUTPUT_OPTION))
@@ -2423,7 +3112,7 @@ SYSCALLS.c.X: $(srcdir)/sys-types.h $(srcdir)/sys-protos.h $(GCC_PASSES) \
-rm -f SYSCALLS.c tmp-SYSCALLS.s
sed -e s/TARGET_GETGROUPS_T/$(TARGET_GETGROUPS_T)/ \
$(srcdir)/sys-types.h $(srcdir)/sys-protos.h > SYSCALLS.c
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) \
-aux-info $@ -S -o tmp-SYSCALLS.s SYSCALLS.c
-rm -f SYSCALLS.c tmp-SYSCALLS.s
@@ -2458,25 +3147,28 @@ test-protoize-simple: ./protoize ./unprotoize $(GCC_PASSES)
-rm -f tmp-proto.[cs] tmp-proto$(objext)
# gcov-iov.c is run on the build machine to generate gcov-iov.h from version.c
-gcov-iov.o: gcov-iov.c version.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) coretypes.h $(TM_H)
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) $(srcdir)/gcov-iov.c $(OUTPUT_OPTION)
-gcov-iov$(build_exeext): gcov-iov.o
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) gcov-iov.o -o $@
+build/gcov-iov.o: gcov-iov.c $(BCONFIG_H) coretypes.h $(GTM_H) \
+ $(SYSTEM_H) coretypes.h $(TM_H)
+
+build/gcov-iov$(build_exeext): build/gcov-iov.o
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) build/gcov-iov.o -o $@
+
gcov-iov.h: s-iov
-s-iov: gcov-iov$(build_exeext) $(srcdir)/move-if-change
- ./gcov-iov$(build_exeext) > tmp-gcov-iov.h
- $(SHELL) $(srcdir)/move-if-change tmp-gcov-iov.h gcov-iov.h
+s-iov: build/gcov-iov$(build_exeext) $(BASEVER) $(DEVPHASE)
+ build/gcov-iov$(build_exeext) '$(BASEVER_c)' '$(DEVPHASE_c)' \
+ > tmp-gcov-iov.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-gcov-iov.h gcov-iov.h
$(STAMP) s-iov
-gcov.o: gcov.c gcov-io.h gcov-io.c gcov-iov.h intl.h $(SYSTEM_H) coretypes.h $(TM_H) $(CONFIG_H)
-gcov-dump.o: gcov-dump.c gcov-io.h gcov-io.c gcov-iov.h $(SYSTEM_H) coretypes.h $(TM_H) $(CONFIG_H)
+gcov.o: gcov.c gcov-io.c $(GCOV_IO_H) intl.h $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(CONFIG_H) version.h
+gcov-dump.o: gcov-dump.c gcov-io.c $(GCOV_IO_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(CONFIG_H)
-# Only one of 'gcov' or 'gcov.exe' is actually built, depending
-# upon whether $(exeext) is empty or not.
-GCOV_OBJS = gcov.o intl.o version.o
+GCOV_OBJS = gcov.o intl.o version.o errors.o
gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) $(GCOV_OBJS) $(LIBS) -o $@
-GCOV_DUMP_OBJS = gcov-dump.o version.o
+GCOV_DUMP_OBJS = gcov-dump.o version.o errors.o
gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) $(GCOV_DUMP_OBJS) $(LIBS) -o $@
#
@@ -2485,7 +3177,7 @@ gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS)
# be rebuilt.
# Build the include directory
-stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h
+stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h $(UNWIND_H)
# Copy in the headers provided with gcc.
# The sed command gets just the last file name component;
# this is necessary because VPATH could add a dirname.
@@ -2503,64 +3195,76 @@ stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h
done
rm -f include/limits.h
cp xlimits.h include/limits.h
+ rm -f include/unwind.h
+ cp $(UNWIND_H) include/unwind.h
chmod a+r include/limits.h
# Install the README
rm -f include/README
- cp $(srcdir)/README-fixinc include/README
+ cp $(srcdir)/../fixincludes/README-fixinc include/README
chmod a+r include/README
$(STAMP) $@
-# fixinc.sh depends on this, not on specs directly.
-# The idea is to make sure specs gets built, but not rerun fixinc.sh
-# after each stage just because specs' mtime has changed.
-specs.ready: specs
- -if [ -f specs.ready ] ; then \
- true; \
- else \
- $(STAMP) specs.ready; \
- fi
-
-# Until someone fixes this recursive make nightmare (please note where
-# BUILD_CFLAGS and WARN_CFLAGS are first expanded below versus which
-# later make invocation has the fine-grain -warn markings for fixinc):
-fixinc.sh-warn = -Wno-error
-
-FIXINCSRCDIR=$(srcdir)/fixinc
-fixinc.sh: $(FIXINCSRCDIR)/mkfixinc.sh $(FIXINCSRCDIR)/fixincl.c \
- $(FIXINCSRCDIR)/procopen.c $(FIXINCSRCDIR)/server.c \
- $(FIXINCSRCDIR)/server.h $(FIXINCSRCDIR)/inclhack.def specs.ready
- (MAKE="$(MAKE)"; srcdir=`cd $(srcdir)/fixinc && ${PWD_COMMAND}` ; \
- CC="$(CC_FOR_BUILD)"; CFLAGS="$(BUILD_CFLAGS)"; LDFLAGS="$(BUILD_LDFLAGS)"; \
- WARN_CFLAGS="$(WARN_CFLAGS)"; LIBERTY=`${PWD_COMMAND}`/"$(BUILD_LIBIBERTY)"; \
- export MAKE srcdir CC CFLAGS LDFLAGS WARN_CFLAGS LIBERTY; \
- cd ./fixinc && \
- $(SHELL) $${srcdir}/mkfixinc.sh $(build) $(target))
-
.PHONY: install-gcc-tooldir
install-gcc-tooldir:
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(gcc_tooldir)
+ $(mkinstalldirs) $(DESTDIR)$(gcc_tooldir)
+
+macro_list: s-macro_list; @true
+s-macro_list : $(GCC_PASSES)
+ echo | $(GCC_FOR_TARGET) -E -dM - | \
+ sed -n -e 's/^#define \([^_][a-zA-Z0-9_]*\).*/\1/p' \
+ -e 's/^#define \(_[^_A-Z][a-zA-Z0-9_]*\).*/\1/p' | \
+ sort -u > tmp-macro_list
+ $(SHELL) $(srcdir)/../move-if-change tmp-macro_list macro_list
+ $(STAMP) s-macro_list
+
+# The line below is supposed to avoid accidentally matching the
+# built-in suffix rule `.o:' to build fixincl out of fixincl.o. You'd
+# expect fixincl to be newer than fixincl.o, such that this situation
+# would never come up. As it turns out, if you use ccache with
+# CCACHE_HARDLINK enabled, the compiler doesn't embed the current
+# working directory in object files (-g absent, or -fno-working-dir
+# present), and build and host are the same, fixincl for the host will
+# build after fixincl for the build machine, getting a cache hit,
+# thereby updating the timestamp of fixincl.o in the host tree.
+# Because of CCACHE_HARDLINK, this will also update the timestamp in
+# the build tree, and so fixincl in the build tree will appear to be
+# out of date. Yuck.
+../$(build_subdir)/fixincludes/fixincl: ; @ :
# Build fixed copies of system files.
-stmp-fixinc: fixinc.sh gsyslimits.h
- @if test ! -d ${SYSTEM_HEADER_DIR}; then \
+# Abort if no system headers available, unless building a crosscompiler.
+# FIXME: abort unless building --without-headers would be more accurate and less ugly
+stmp-fixinc: gsyslimits.h macro_list \
+ $(build_objdir)/fixincludes/fixincl \
+ $(build_objdir)/fixincludes/fixinc.sh
+ @if ! $(inhibit_libc) && test ! -d ${SYSTEM_HEADER_DIR}; then \
echo The directory that should contain system headers does not exist: >&2 ; \
echo " ${SYSTEM_HEADER_DIR}" >&2 ; \
- if test "x${SYSTEM_HEADER_DIR}" = "x${gcc_tooldir}/sys-include"; \
+ tooldir_sysinc=`echo "${gcc_tooldir}/sys-include" | sed -e :a -e "s,[^/]*/\.\.\/,," -e ta`; \
+ if test "x${SYSTEM_HEADER_DIR}" = "x$${tooldir_sysinc}"; \
then sleep 1; else exit 1; fi; \
fi
rm -rf include; mkdir include
-chmod a+rx include
- (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); ${PWD_COMMAND}`; \
- SHELL='$(SHELL)' ;\
- export TARGET_MACHINE srcdir SHELL ; \
- $(SHELL) ./fixinc.sh `${PWD_COMMAND}`/include $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS); \
- rm -f include/syslimits.h; \
- if [ -f include/limits.h ]; then \
- mv include/limits.h include/syslimits.h; \
+ if [ -d ../prev-gcc ]; then \
+ cd ../prev-gcc && \
+ $(MAKE) real-$(INSTALL_HEADERS_DIR) DESTDIR=`pwd`/../gcc/ \
+ libsubdir=. ; \
else \
- cp $(srcdir)/gsyslimits.h include/syslimits.h; \
- fi; \
- chmod a+r include/syslimits.h)
+ (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); ${PWD_COMMAND}`; \
+ SHELL='$(SHELL)'; MACRO_LIST=`${PWD_COMMAND}`/macro_list ; \
+ export TARGET_MACHINE srcdir SHELL MACRO_LIST && \
+ cd $(build_objdir)/fixincludes && \
+ $(SHELL) ./fixinc.sh ../../gcc/include \
+ $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS) ); \
+ rm -f include/syslimits.h; \
+ if [ -f include/limits.h ]; then \
+ mv include/limits.h include/syslimits.h; \
+ else \
+ cp $(srcdir)/gsyslimits.h include/syslimits.h; \
+ fi; \
+ fi
+ chmod a+r include/syslimits.h
$(STAMP) stmp-fixinc
# Files related to the fixproto script.
@@ -2579,49 +3283,53 @@ deduced.h: $(GCC_PASSES) $(srcdir)/scan-types.sh stmp-int-hdrs
$(STAMP) deduced.h; \
fi
-GEN_PROTOS_OBJS = gen-protos.o scan.o
-gen-protos$(build_exeext): $(GEN_PROTOS_OBJS)
+GEN_PROTOS_OBJS = build/gen-protos.o build/scan.o $(BUILD_ERRORS)
+build/gen-protos$(build_exeext): $(GEN_PROTOS_OBJS)
${CC_FOR_BUILD} $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
$(GEN_PROTOS_OBJS) $(BUILD_LIBS)
-gen-protos.o: gen-protos.c scan.h $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H)
+build/gen-protos.o: gen-protos.c scan.h $(BCONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(GTM_H) errors.h
-scan.o: scan.c scan.h $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H)
+build/scan.o: scan.c scan.h $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H)
-xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h gen-protos$(build_exeext) Makefile
+xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h \
+ build/gen-protos$(build_exeext) Makefile
sed -e s/TARGET_GETGROUPS_T/$(TARGET_GETGROUPS_T)/ \
deduced.h $(srcdir)/sys-protos.h > tmp-fixtmp.c
mv tmp-fixtmp.c fixtmp.c
$(GCC_FOR_TARGET) fixtmp.c -w -U__SIZE_TYPE__ -U__PTRDIFF_TYPE__ -U__WCHAR_TYPE__ -E \
| sed -e 's/ / /g' -e 's/ *(/ (/g' -e 's/ [ ]*/ /g' -e 's/( )/()/' \
- | $(RUN_GEN) ./gen-protos >xsys-protos.hT
+ | $(RUN_GEN) build/gen-protos >xsys-protos.hT
mv xsys-protos.hT xsys-protos.h
rm -rf fixtmp.c
# This is nominally a 'build' program, but it's run only when host==build,
# so we can (indeed, must) use $(LIBDEPS) and $(LIBS).
-fix-header$(build_exeext): fix-header.o scan-decls.o scan.o xsys-protos.h \
- c-incpath.o cppdefault.o prefix.o $(LIBDEPS) libcpp.a
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ fix-header.o \
- c-incpath.o cppdefault.o scan-decls.o prefix.o scan.o libcpp.a $(LIBS)
+build/fix-header$(build_exeext): build/fix-header.o build/scan-decls.o \
+ build/scan.o xsys-protos.h c-incpath.o cppdefault.o prefix.o \
+ $(BUILD_ERRORS) $(LIBDEPS)
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
+ build/fix-header.o c-incpath.o cppdefault.o build/scan-decls.o prefix.o \
+ build/scan.o $(BUILD_ERRORS) $(LIBS)
-fix-header.o: fix-header.c $(OBSTACK_H) scan.h \
+build/fix-header.o: fix-header.c $(OBSTACK_H) scan.h errors.h \
xsys-protos.h $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) $(CPPLIB_H)
-scan-decls.o: scan-decls.c scan.h $(CPPLIB_H) $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H)
+build/scan-decls.o: scan-decls.c scan.h $(CPPLIB_H) $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H)
# stmp-fixproto depends on this, not on fix-header directly.
# The idea is to make sure fix-header gets built,
# but not rerun fixproto after each stage
# just because fix-header's mtime has changed.
-fixhdr.ready: fix-header$(build_exeext)
+fixhdr.ready: build/fix-header$(build_exeext)
-if [ -f fixhdr.ready ] ; then \
true; \
else \
$(STAMP) fixhdr.ready; \
fi
-# stmp-int-headers is to make sure fixincludes has already finished.
+# stmp-int-hdrs is to make sure fixincludes has already finished.
# The if statement is so that we don't run fixproto a second time
# if it has already been run on the files in `include'.
stmp-fixproto: fixhdr.ready fixproto stmp-int-hdrs
@@ -2629,7 +3337,8 @@ stmp-fixproto: fixhdr.ready fixproto stmp-int-hdrs
else \
: This line works around a 'make' bug in BSDI 1.1.; \
FIXPROTO_DEFINES="$(FIXPROTO_DEFINES)"; export FIXPROTO_DEFINES; \
- mkinstalldirs="$(SHELL) $(srcdir)/mkinstalldirs"; \
+ FIX_HEADER="build/fix-header$(build_exeext)"; export FIX_HEADER; \
+ mkinstalldirs="$(mkinstalldirs)"; \
export mkinstalldirs; \
if [ -d "$(SYSTEM_HEADER_DIR)" ]; then \
$(SHELL) ${srcdir}/fixproto include include $(SYSTEM_HEADER_DIR); \
@@ -2638,6 +3347,12 @@ stmp-fixproto: fixhdr.ready fixproto stmp-int-hdrs
$(STAMP) include/fixed; \
fi
$(STAMP) stmp-fixproto
+
+# We can't run fixproto (it's being built for a different host), but we still
+# need to install it so that the user can run it when the compiler is
+# installed.
+stmp-install-fixproto: fixproto
+ $(STAMP) $@
#
# Remake the info files.
@@ -2651,26 +3366,43 @@ info: $(INFOFILES) lang.info @GENINSRC@ srcinfo lang.srcinfo
srcinfo: $(INFOFILES)
-cp -p $^ $(srcdir)/doc
-TEXI_CPP_FILES = cpp.texi fdl.texi cppenv.texi cppopts.texi
-
-TEXI_GCC_FILES = gcc.texi gcc-common.texi frontends.texi standards.texi \
- invoke.texi extend.texi md.texi objc.texi gcov.texi trouble.texi \
- bugreport.texi service.texi contribute.texi compat.texi funding.texi \
- gnu.texi gpl.texi fdl.texi contrib.texi cppenv.texi cppopts.texi
-
-TEXI_GCCINT_FILES = gccint.texi gcc-common.texi contribute.texi makefile.texi \
- configterms.texi portability.texi interface.texi passes.texi \
- c-tree.texi rtl.texi md.texi tm.texi hostconfig.texi fragments.texi \
- configfiles.texi collect2.texi headerdirs.texi funding.texi gnu.texi \
- gpl.texi fdl.texi contrib.texi languages.texi sourcebuild.texi \
- gty.texi libgcc.texi
-
-TEXI_GCCINSTALL_FILES = install.texi install-old.texi fdl.texi
-
-TEXI_CPPINT_FILES = cppinternals.texi
-
-# The *.1, *.7, *.info, and *.dvi files are being generated from implicit
-# patterns. To use them, put each of the specific target with with their
+TEXI_CPP_FILES = cpp.texi fdl.texi cppenv.texi cppopts.texi \
+ gcc-common.texi gcc-vers.texi
+
+TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi \
+ standards.texi invoke.texi extend.texi md.texi objc.texi \
+ gcov.texi trouble.texi bugreport.texi service.texi \
+ contribute.texi compat.texi funding.texi gnu.texi gpl.texi \
+ fdl.texi contrib.texi cppenv.texi cppopts.texi \
+ implement-c.texi
+
+TEXI_GCCINT_FILES = gccint.texi gcc-common.texi gcc-vers.texi \
+ contribute.texi makefile.texi configterms.texi options.texi \
+ portability.texi interface.texi passes.texi c-tree.texi \
+ rtl.texi md.texi tm.texi hostconfig.texi fragments.texi \
+ configfiles.texi collect2.texi headerdirs.texi funding.texi \
+ gnu.texi gpl.texi fdl.texi contrib.texi languages.texi \
+ sourcebuild.texi gty.texi libgcc.texi cfg.texi tree-ssa.texi \
+ loop.texi
+
+TEXI_GCCINSTALL_FILES = install.texi install-old.texi fdl.texi \
+ gcc-common.texi gcc-vers.texi
+
+TEXI_CPPINT_FILES = cppinternals.texi gcc-common.texi gcc-vers.texi
+
+# gcc-vers.texi is generated from the version files.
+gcc-vers.texi: $(BASEVER) $(DEVPHASE)
+ (echo "@set version-GCC $(BASEVER_c)"; \
+ if [ "$(DEVPHASE_c)" = "experimental" ]; \
+ then echo "@set DEVELOPMENT"; \
+ else echo "@clear DEVELOPMENT"; \
+ fi) > $@T
+ echo "@set srcdir $(srcdir)" >> $@T
+ mv -f $@T $@
+
+
+# The *.1, *.7, *.info, *.dvi, and *.pdf files are being generated from implicit
+# patterns. To use them, put each of the specific targets with its
# specific dependencies but no build commands.
doc/cpp.info: $(TEXI_CPP_FILES)
@@ -2680,15 +3412,15 @@ doc/cppinternals.info: $(TEXI_CPPINT_FILES)
doc/%.info: %.texi
if [ x$(BUILD_INFO) = xinfo ]; then \
- $(MAKEINFO) $(MAKEINFOFLAGS) -I $(docdir) \
- -I $(docdir)/include -o $@ $<; \
+ $(MAKEINFO) $(MAKEINFOFLAGS) -I . -I $(gcc_docdir) \
+ -I $(gcc_docdir)/include -o $@ $<; \
fi
# Duplicate entry to handle renaming of gccinstall.info
doc/gccinstall.info: $(TEXI_GCCINSTALL_FILES)
if [ x$(BUILD_INFO) = xinfo ]; then \
- $(MAKEINFO) $(MAKEINFOFLAGS) -I $(docdir) \
- -I $(docdir)/include -o $@ $<; \
+ $(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \
+ -I $(gcc_docdir)/include -o $@ $<; \
fi
doc/cpp.dvi: $(TEXI_CPP_FILES)
@@ -2696,19 +3428,65 @@ doc/gcc.dvi: $(TEXI_GCC_FILES)
doc/gccint.dvi: $(TEXI_GCCINT_FILES)
doc/cppinternals.dvi: $(TEXI_CPPINT_FILES)
+doc/cpp.pdf: $(TEXI_CPP_FILES)
+doc/gcc.pdf: $(TEXI_GCC_FILES)
+doc/gccint.pdf: $(TEXI_GCCINT_FILES)
+doc/cppinternals.pdf: $(TEXI_CPPINT_FILES)
+
+$(build_htmldir)/cpp/index.html: $(TEXI_CPP_FILES)
+$(build_htmldir)/gcc/index.html: $(TEXI_GCC_FILES)
+$(build_htmldir)/gccint/index.html: $(TEXI_GCCINT_FILES)
+$(build_htmldir)/cppinternals/index.html: $(TEXI_CPPINT_FILES)
+
dvi:: doc/gcc.dvi doc/gccint.dvi doc/gccinstall.dvi doc/cpp.dvi \
- doc/cppinternals.dvi
+ doc/cppinternals.dvi lang.dvi
doc/%.dvi: %.texi
- $(TEXI2DVI) -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+ $(TEXI2DVI) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
# Duplicate entry to handle renaming of gccinstall.dvi
doc/gccinstall.dvi: $(TEXI_GCCINSTALL_FILES)
- $(TEXI2DVI) -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+ $(TEXI2DVI) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+pdf:: doc/gcc.pdf doc/gccint.pdf doc/gccinstall.pdf doc/cpp.pdf \
+ doc/cppinternals.pdf lang.pdf
+
+doc/%.pdf: %.texi
+ $(TEXI2PDF) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+# Duplicate entry to handle renaming of gccinstall.pdf
+doc/gccinstall.pdf: $(TEXI_GCCINSTALL_FILES)
+ $(TEXI2PDF) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+# List the directories or single hmtl files which are installed by
+# install-html. The lang.html file triggers language fragments to build
+# html documentation. Installing language fragment documentation is not
+# yet supported.
+HTMLS_INSTALL=$(build_htmldir)/cpp $(build_htmldir)/gcc \
+ $(build_htmldir)/gccinstall $(build_htmldir)/gccint \
+ $(build_htmldir)/cppinternals
+
+# List the html file targets.
+HTMLS_BUILD=$(build_htmldir)/cpp/index.html $(build_htmldir)/gcc/index.html \
+ $(build_htmldir)/gccinstall/index.html $(build_htmldir)/gccint/index.html \
+ $(build_htmldir)/cppinternals/index.html lang.html
+
+html:: $(HTMLS_BUILD)
+
+$(build_htmldir)/%/index.html: %.texi
+ $(mkinstalldirs) $(@D)
+ rm -f $(@D)/*
+ $(TEXI2HTML) -I $(abs_docdir) -I $(abs_docdir)/include -o $(@D) $<
+
+# Duplicate entry to handle renaming of gccinstall
+$(build_htmldir)/gccinstall/index.html: $(TEXI_GCCINSTALL_FILES)
+ $(mkinstalldirs) $(@D)
+ echo rm -f $(@D)/*
+ $(TEXI2HTML) -I $(abs_docdir) -I $(abs_docdir)/include -o $(@D) $<
MANFILES = doc/gcov.1 doc/cpp.1 doc/gcc.1 doc/gfdl.7 doc/gpl.7 doc/fsf-funding.7
-generated-manpages: man
+generated-manpages: man
man: $(MANFILES) lang.man @GENINSRC@ srcman lang.srcman
@@ -2735,7 +3513,7 @@ doc/%.7: %.pod
cpp.pod: cpp.texi cppenv.texi cppopts.texi
# These next rules exist because the output name is not the same as
-# the input name, so our implict %.pod rule will not work.
+# the input name, so our implicit %.pod rule will not work.
gcc.pod: invoke.texi cppenv.texi cppopts.texi
$(STAMP) $@
@@ -2748,6 +3526,18 @@ fsf-funding.pod: funding.texi
-$(TEXI2POD) $< > $@
#
+# clean-target removes all files made by compilation.
+# This can be added to over time.
+
+clean-target: clean-target-libgcc
+
+clean-target-libgcc:
+ test ! -d libgcc || \
+ (cd libgcc && find . -type d -print) | \
+ while read d; do rm -f $$d/libgcc.a || : ; done
+ test ! -d libgcc || rm -r libgcc
+ test ! -f stmp-dirs || rm stmp-dirs
+
# Deletion of files made during compilation.
# There are four levels of this:
# `mostlyclean', `clean', `distclean' and `maintainer-clean'.
@@ -2762,13 +3552,12 @@ fsf-funding.pod: funding.texi
# (less duplicated code).
mostlyclean: lang.mostlyclean
- -rm -f $(STAGESTUFF)
+ -rm -f $(STAGECOPYSTUFF) $(STAGEMOVESTUFF)
-rm -f *$(coverageexts)
-rm -rf libgcc
-# Delete the temporary source copies for cross compilation.
- -rm -f $(BUILD_PREFIX_1)rtl.c $(BUILD_PREFIX_1)print-rtl.c
- -rm -f $(BUILD_PREFIX_1)bitmap.c $(BUILD_PREFIX_1)errors.c
- -rm -f $(BUILD_PREFIX_1)ggc-none.c print-rtl1.c
+# Delete build programs
+ -rm -f build/*
+ -rm -f mddeps.mk
# Delete the temp files made in the course of building libgcc.a.
-rm -f xlimits.h
# Delete other built files.
@@ -2783,11 +3572,8 @@ mostlyclean: lang.mostlyclean
-rm -f specs $(SPECS) SYSCALLS.c.X SYSCALLS.c
-rm -f collect collect2 mips-tfile mips-tdump
# Delete files generated for fixproto
- -rm -rf fix-header$(build_exeext) xsys-protos.h deduced.h tmp-deduced.h \
+ -rm -rf $(build_exeext) xsys-protos.h deduced.h tmp-deduced.h \
gen-protos$(build_exeext) fixproto.list fixtmp.* fixhdr.ready
-# Delete files generated for fixincl
- -rm -rf fixincl fixinc.sh specs.ready
- (cd fixinc && $(MAKE) clean)
# Delete unwanted output files from TeX.
-rm -f *.toc *.log *.vr *.fn *.cp *.tp *.ky *.pg
-rm -f */*.toc */*.log */*.vr */*.fn */*.cp */*.tp */*.ky */*.pg
@@ -2800,6 +3586,8 @@ mostlyclean: lang.mostlyclean
# Delete files generated by gengtype.c
-rm -f gtype-*
-rm -f gt-*
+# Delete genchecksum outputs
+ -rm -f *-checksum.c
# Delete all files made by compilation
# that don't exist in the distribution.
@@ -2808,9 +3596,11 @@ clean: mostlyclean lang.clean
-rm -f libgcc_s*
-rm -f libunwind*
-rm -f config.h tconfig.h bconfig.h tm_p.h tm.h
+ -rm -f options.c options.h optionlist
-rm -f cs-*
-rm -rf libgcc
-rm -f doc/*.dvi
+ -rm -f doc/*.pdf
# Delete the include directory.
-rm -rf include
# Delete files used by the "multilib" facility (including libgcc subdirs).
@@ -2836,7 +3626,7 @@ distclean: clean lang.distclean
-rm -f Makefile *.oaux
-rm -f gthr-default.h
-rm -f */stage1 */stage2 */stage3 */stage4 */include */stageprofile */stagefeedback
- -rm -f c-parse.y c-parse.c c-parse.output TAGS */TAGS
+ -rm -f TAGS */TAGS
-rm -f *.asm
-rm -f site.exp site.bak testsuite/site.exp testsuite/site.bak
-rm -f testsuite/*.log testsuite/*.sum
@@ -2844,12 +3634,11 @@ distclean: clean lang.distclean
-cd testsuite && rm -f *.out *.gcov *$(coverageexts)
-rm -rf ${QMTEST_DIR} stamp-qmtest
-rm -f cxxmain.c
- -rm -f mklibgcc mkheaders gccbug .gdbinit configargs.h
+ -rm -f mklibgcc gccbug .gdbinit configargs.h
-rm -f gcov.pod
- -rm -f fixinc/Makefile
# Delete po/*.gmo only if we are not building in the source directory.
-if [ ! -f po/exgettext ]; then rm -f po/*.gmo; fi
- -rmdir ada cp f java objc fixinc intl po testsuite 2>/dev/null
+ -rmdir ada cp f java objc intl po testsuite 2>/dev/null
# Get rid of every file that's generated from some other file, except for `configure'.
# Most of these files ARE PRESENT in the GCC distribution.
@@ -2857,10 +3646,9 @@ maintainer-clean:
@echo 'This command is intended for maintainers to use; it'
@echo 'deletes files that may need special tools to rebuild.'
$(MAKE) lang.maintainer-clean distclean
- -rm -f $(srcdir)/c-parse.y $(srcdir)/c-parse.c
-rm -f cpp.??s cpp.*aux
-rm -f gcc.??s gcc.*aux
- -rm -f $(docdir)/*.info $(docdir)/*.1 $(docdir)/*.7 $(docdir)/*.dvi
+ -rm -f $(gcc_docdir)/*.info $(gcc_docdir)/*.1 $(gcc_docdir)/*.7 $(gcc_docdir)/*.dvi $(gcc_docdir)/*.pdf
#
# Entry points `install' and `uninstall'.
# Also use `install-collect2' to install collect2 when the config files don't.
@@ -2870,10 +3658,10 @@ maintainer-clean:
# broken is small.
install: install-common $(INSTALL_HEADERS) $(INSTALL_LIBGCC) \
install-cpp install-man install-info install-@POSUB@ \
- lang.install-normal install-driver
+ install-driver
# Handle cpp installation.
-install-cpp: cpp$(exeext)
+install-cpp: installdirs cpp$(exeext)
-rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext)
-$(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext)
-if [ x$(cpp_install_dir) != x ]; then \
@@ -2884,14 +3672,14 @@ install-cpp: cpp$(exeext)
# Create the installation directories.
# $(libdir)/gcc/include isn't currently searched by cpp.
installdirs:
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(libsubdir)
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(libexecsubdir)
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(includedir)
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(infodir)
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(slibdir)
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(man1dir)
- $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(man7dir)
+ $(mkinstalldirs) $(DESTDIR)$(libsubdir)
+ $(mkinstalldirs) $(DESTDIR)$(libexecsubdir)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
+ $(mkinstalldirs) $(DESTDIR)$(infodir)
+ $(mkinstalldirs) $(DESTDIR)$(slibdir)
+ $(mkinstalldirs) $(DESTDIR)$(man1dir)
+ $(mkinstalldirs) $(DESTDIR)$(man7dir)
# Install the compiler executables built during cross compilation.
install-common: native $(EXTRA_PARTS) lang.install-common installdirs
@@ -2902,7 +3690,7 @@ install-common: native $(EXTRA_PARTS) lang.install-common installdirs
else true; \
fi; \
done
- for file in $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2) ..; do \
+ for file in $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) ..; do \
if [ x"$$file" != x.. ]; then \
rm -f $(DESTDIR)$(libexecsubdir)/$$file; \
$(INSTALL_PROGRAM) $$file $(DESTDIR)$(libexecsubdir)/$$file; \
@@ -2915,12 +3703,11 @@ install-common: native $(EXTRA_PARTS) lang.install-common installdirs
chmod a-x $(DESTDIR)$(libsubdir)/$$file; \
else true; fi; \
done
-# Don't mess with specs if it doesn't exist yet.
- -if [ -f specs ] ; then \
- rm -f $(DESTDIR)$(libsubdir)/specs; \
- $(INSTALL_DATA) $(SPECS) $(DESTDIR)$(libsubdir)/specs; \
- chmod a-x $(DESTDIR)$(libsubdir)/specs; \
- fi
+# We no longer install the specs file because its presence makes the
+# driver slower, and because people who need it can recreate it by
+# using -dumpspecs. We remove any old version because it would
+# otherwise override the specs built into the driver.
+ rm -f $(DESTDIR)$(libsubdir)/specs
# Install protoize if it was compiled.
-if [ -f protoize$(exeext) ]; then \
rm -f $(DESTDIR)$(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext); \
@@ -2939,15 +3726,15 @@ install-common: native $(EXTRA_PARTS) lang.install-common installdirs
fi
$(INSTALL_SCRIPT) gccbug $(DESTDIR)$(bindir)/$(GCCBUG_INSTALL_NAME)
-# Install the driver program as $(target_noncanonical)-gcc,
+# Install the driver program as $(target_noncanonical)-gcc,
# $(target_noncanonical)-gcc-$(version)
# and also as either gcc (if native) or $(gcc_tooldir)/bin/gcc.
install-driver: installdirs xgcc$(exeext)
-rm -f $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
-$(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
- -rm -f $(DESTDIR)$(bindir)/$(target_noncanonical)-gcc-$(version)
+ -rm -f $(DESTDIR)$(bindir)/$(target_noncanonical)-gcc-$(version)$(exeext)
-( cd $(DESTDIR)$(bindir) && \
- $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_noncanonical)-gcc-$(version) )
+ $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_noncanonical)-gcc-$(version)$(exeext) )
-if [ -f gcc-cross$(exeext) ] ; then \
if [ -d $(DESTDIR)$(gcc_tooldir)/bin/. ] ; then \
rm -f $(DESTDIR)$(gcc_tooldir)/bin/gcc$(exeext); \
@@ -2968,7 +3755,8 @@ install-info:: doc installdirs \
$(DESTDIR)$(infodir)/gcc.info \
$(DESTDIR)$(infodir)/cppinternals.info \
$(DESTDIR)$(infodir)/gccinstall.info \
- $(DESTDIR)$(infodir)/gccint.info
+ $(DESTDIR)$(infodir)/gccint.info \
+ lang.install-info
$(DESTDIR)$(infodir)/%.info: doc/%.info installdirs
rm -f $@
@@ -2985,8 +3773,27 @@ $(DESTDIR)$(infodir)/%.info: doc/%.info installdirs
else true; fi; \
else true; fi;
+html__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+
+install-html: $(HTMLS_BUILD)
+ @$(NORMAL_INSTALL)
+ test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
+ @list='$(HTMLS_INSTALL)'; for p in $$list; do \
+ if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; fi; \
+ f=$(html__strip_dir) \
+ if test -d "$$d$$p"; then \
+ echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
+ echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \
+ else \
+ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \
+ fi; \
+ done
+
# Install the man pages.
-install-man: installdirs lang.install-man \
+install-man: lang.install-man \
$(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext) \
$(DESTDIR)$(man1dir)/$(CPP_INSTALL_NAME)$(man1ext) \
$(DESTDIR)$(man1dir)/$(GCOV_INSTALL_NAME)$(man1ext) \
@@ -2994,24 +3801,24 @@ install-man: installdirs lang.install-man \
$(DESTDIR)$(man7dir)/gfdl$(man7ext) \
$(DESTDIR)$(man7dir)/gpl$(man7ext)
-$(DESTDIR)$(man7dir)/%$(man7ext): doc/%.7
+$(DESTDIR)$(man7dir)/%$(man7ext): doc/%.7 installdirs
-rm -f $@
-$(INSTALL_DATA) $< $@
-chmod a-x $@
-$(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext): doc/gcc.1
+$(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext): doc/gcc.1 installdirs
-rm -f $@
- -$(INSTALL_DATA) $< $@
+ -$(INSTALL_DATA) $< $@
-chmod a-x $@
-$(DESTDIR)$(man1dir)/$(CPP_INSTALL_NAME)$(man1ext): doc/cpp.1
+$(DESTDIR)$(man1dir)/$(CPP_INSTALL_NAME)$(man1ext): doc/cpp.1 installdirs
-rm -f $@
- -$(INSTALL_DATA) $< $@
+ -$(INSTALL_DATA) $< $@
-chmod a-x $@
-$(DESTDIR)$(man1dir)/$(GCOV_INSTALL_NAME)$(man1ext): doc/gcov.1
+$(DESTDIR)$(man1dir)/$(GCOV_INSTALL_NAME)$(man1ext): doc/gcov.1 installdirs
-rm -f $@
- -$(INSTALL_DATA) $< $@
+ -$(INSTALL_DATA) $< $@
-chmod a-x $@
# Install the library.
@@ -3020,6 +3827,7 @@ install-libgcc: libgcc.mk libgcc.a libgcov.a installdirs
CFLAGS="$(CFLAGS) $(WARN_CFLAGS)" \
CONFIG_H="$(TCONFIG_H)" \
MAKEOVERRIDES= \
+ mkinstalldirs='$(mkinstalldirs)' \
-f libgcc.mk install
# Install multiple versions of libgcc.a, libgcov.a.
@@ -3028,6 +3836,7 @@ install-multilib: stmp-multilib installdirs
CFLAGS="$(CFLAGS) $(WARN_CFLAGS)" \
CONFIG_H="$(CONFIG_H)" \
MAKEOVERRIDES= \
+ mkinstalldirs='$(mkinstalldirs)' \
-f libgcc.mk install
# Install all the header files built in the include subdirectory.
@@ -3053,6 +3862,13 @@ install-include-dir: installdirs
mkdir $(DESTDIR)$(libsubdir)/include
-chmod a+rx $(DESTDIR)$(libsubdir)/include
+# Create or recreate the install-tools include file directory.
+itoolsdir = $(libexecsubdir)/install-tools
+itoolsdatadir = $(libsubdir)/install-tools
+install-itoolsdirs: installdirs
+ $(mkinstalldirs) $(DESTDIR)$(itoolsdatadir)/include
+ $(mkinstalldirs) $(DESTDIR)$(itoolsdir)
+
# Install the include directory using tar.
install-headers-tar: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
# We use `pwd`/include instead of just include to problems with CDPATH
@@ -3075,37 +3891,38 @@ install-headers-cpio: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
install-headers-cp: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
cp -p -r include $(DESTDIR)$(libsubdir)
-itoolsdir = $(libexecsubdir)/install-tools
-itoolsdatadir = $(libsubdir)/install-tools
-# Don't install the headers. Instead, install appropriate scripts
-# and supporting files for fixincludes to be run later.
-install-mkheaders: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir \
- mkheaders xlimits.h
- -rm -rf $(DESTDIR)$(itoolsdir) $(DESTDIR)$(itoolsdatadir)
- $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(itoolsdatadir)/include
- $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(itoolsdir)
+# Targets without dependencies, for use in prev-gcc during bootstrap.
+real-install-headers-tar:
+ (cd `${PWD_COMMAND}`/include ; \
+ tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include; tar xpf - )
+
+real-install-headers-cpio:
+ cd `${PWD_COMMAND}`/include ; \
+ find . -print | cpio -pdum $(DESTDIR)$(libsubdir)/include
+
+real-install-headers-cp:
+ cp -p -r include $(DESTDIR)$(libsubdir)
+
+# Install supporting files for fixincludes to be run later.
+install-mkheaders: stmp-int-hdrs $(STMP_FIXPROTO) install-itoolsdirs \
+ macro_list xlimits.h
for file in $(USER_H); do \
realfile=`echo $$file | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
$(INSTALL_DATA) $$file \
$(DESTDIR)$(itoolsdatadir)/include/$$realfile ; \
done
$(INSTALL_DATA) xlimits.h $(DESTDIR)$(itoolsdatadir)/include/limits.h
- if [ x$(STMP_FIXINC) != x ] ; then \
- $(INSTALL_DATA) $(srcdir)/README-fixinc \
- $(DESTDIR)$(itoolsdatadir)/include/README ; \
- $(INSTALL_SCRIPT) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
- $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
- $(INSTALL_DATA) $(srcdir)/gsyslimits.h \
- $(DESTDIR)$(itoolsdatadir)/gsyslimits.h ; \
- else :; fi
+ $(INSTALL_DATA) $(UNWIND_H) $(DESTDIR)$(itoolsdatadir)/include/unwind.h
+ $(INSTALL_DATA) $(srcdir)/gsyslimits.h \
+ $(DESTDIR)$(itoolsdatadir)/gsyslimits.h
+ $(INSTALL_DATA) macro_list $(DESTDIR)$(itoolsdatadir)/macro_list
if [ x$(STMP_FIXPROTO) != x ] ; then \
- $(INSTALL_SCRIPT) $(srcdir)/mkinstalldirs \
+ $(INSTALL_SCRIPT) $(mkinstalldirs) \
$(DESTDIR)$(itoolsdir)/mkinstalldirs ; \
$(INSTALL_SCRIPT) $(srcdir)/fixproto $(DESTDIR)$(itoolsdir)/fixproto ; \
- $(INSTALL_PROGRAM) fix-header$(build_exeext) \
+ $(INSTALL_PROGRAM) build/fix-header$(build_exeext) \
$(DESTDIR)$(itoolsdir)/fix-header$(build_exeext) ; \
else :; fi
- $(INSTALL_SCRIPT) mkheaders $(DESTDIR)$(itoolsdir)/mkheaders
echo 'SYSTEM_HEADER_DIR="'"$(SYSTEM_HEADER_DIR)"'"' \
> $(DESTDIR)$(itoolsdatadir)/mkheaders.conf
echo 'OTHER_FIXINCLUDES_DIRS="$(OTHER_FIXINCLUDES_DIRS)"' \
@@ -3161,9 +3978,12 @@ site.exp: ./config.status Makefile
@echo "set build_triplet $(build)" >> ./tmp0
@echo "set target_triplet $(target)" >> ./tmp0
@echo "set target_alias $(target_noncanonical)" >> ./tmp0
+ @echo "set libiconv \"$(LIBICONV)\"" >> ./tmp0
# CFLAGS is set even though it's empty to show we reserve the right to set it.
@echo "set CFLAGS \"\"" >> ./tmp0
@echo "set CXXFLAGS \"\"" >> ./tmp0
+ @echo "set HOSTCC \"$(CC)\"" >> ./tmp0
+ @echo "set HOSTCFLAGS \"$(CFLAGS)\"" >> ./tmp0
@echo "set TESTING_IN_BUILD_TREE 1" >> ./tmp0
@echo "set HAVE_LIBSTDCXX_V3 1" >> ./tmp0
# If newlib has been configured, we need to pass -B to gcc so it can find
@@ -3229,17 +4049,23 @@ $(lang_checks_parallel): site.exp
TESTSUITEDIR = testsuite
$(TESTSUITEDIR)/site.exp: site.exp
- test -d $(TESTSUITEDIR) || mkdir $(TESTSUITEDIR)
+ -test -d $(TESTSUITEDIR) || mkdir $(TESTSUITEDIR)
-rm -f $@
sed '/set tmpdir/ s|testsuite|$(TESTSUITEDIR)|' < site.exp > $@
-$(lang_checks): check-% : $(TESTSUITEDIR)/site.exp
+$(lang_checks): check-% : site.exp
+ -test -d $(TESTSUITEDIR) || mkdir $(TESTSUITEDIR)
+ test -d $(TESTSUITEDIR)/$* || mkdir $(TESTSUITEDIR)/$*
-(rootme=`${PWD_COMMAND}`; export rootme; \
srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
- cd $(TESTSUITEDIR); \
+ cd $(TESTSUITEDIR)/$*; \
+ rm -f tmp-site.exp; \
+ sed '/set tmpdir/ s|testsuite|$(TESTSUITEDIR)/$*|' \
+ < ../../site.exp > tmp-site.exp; \
+ $(SHELL) $${srcdir}/../move-if-change tmp-site.exp site.exp; \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
+ TCL_LIBRARY=`cd .. ; cd $${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool $* $(RUNTESTFLAGS))
@@ -3249,7 +4075,7 @@ check-consistency: testsuite/site.exp
cd testsuite; \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
+ TCL_LIBRARY=`cd .. ; cd $${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool consistency $(RUNTESTFLAGS)
@@ -3308,8 +4134,8 @@ qmtest-gui: ${QMTEST_DIR}/context
# Run Paranoia on real.c.
paranoia.o: $(srcdir)/../contrib/paranoia.cc $(CONFIG_H) $(SYSTEM_H) \
- real.h $(TREE_H)
- g++ -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+ $(REAL_H) $(TREE_H)
+ g++ -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
paranoia: paranoia.o real.o $(LIBIBERTY)
g++ -o $@ paranoia.o real.o $(LIBIBERTY)
@@ -3325,11 +4151,7 @@ TAGS: lang.tags
incs="$$incs --include $$dir/TAGS.sub"; \
fi; \
done; \
- mkdir tmp-tags; \
- mv -f c-parse.[ch] tmp-tags; \
- etags -o TAGS.sub *.y *.h *.c; \
- mv tmp-tags/* .; \
- rmdir tmp-tags; \
+ etags -o TAGS.sub *.y *.h *.c; \
etags --include TAGS.sub $$incs)
# ------------------------------------------------------
@@ -3337,7 +4159,7 @@ TAGS: lang.tags
# ------------------------------------------------------
# A list of files to be destroyed during "lean" builds.
-VOL_FILES=`echo $(BACKEND) $(OBJS) $(C_OBJS) $(LIBCPP_OBJS) *.c *.h gen*`
+VOL_FILES=`echo $(BACKEND) $(OBJS) $(C_OBJS) *.c *.h gen*`
# Flags to pass to stage2 and later recursive makes. Note that the
# WARN_CFLAGS setting can't be to the expansion of GCC_WARN_CFLAGS in
@@ -3358,26 +4180,27 @@ POSTSTAGE1_FLAGS_TO_PASS = \
STAGE2_FLAGS_TO_PASS = \
CFLAGS="$(BOOT_CFLAGS)" \
- WERROR="@WERROR@" \
+ WERROR="$(WERROR_FLAGS)" \
STAGEPROFILE_FLAGS_TO_PASS = \
- CFLAGS="$(BOOT_CFLAGS) -fprofile-generate"
+ CFLAGS="$(BOOT_CFLAGS) -fprofile-generate"
# Files never linked into the final executable produces warnings about missing
# profile.
STAGEFEEDBACK_FLAGS_TO_PASS = \
- CFLAGS="$(BOOT_CFLAGS) -fprofile-use"
+ CFLAGS="$(BOOT_CFLAGS) -fprofile-use -freorder-blocks-and-partition"
# Only build the C compiler for stage1, because that is the only one that
# we can guarantee will build with the native compiler, and also it is the
# only thing useful for building stage2. STAGE1_CFLAGS (via CFLAGS),
# MAKEINFO and MAKEINFOFLAGS are explicitly passed here to make them
# overrideable (for a bootstrap build stage1 also builds gcc.info).
+# The stage1 compiler is always built with checking enabled.
stage1_build:
$(MAKE) CC="$(CC)" libdir=$(libdir) LANGUAGES="$(BOOT_LANGUAGES)" \
- CFLAGS="$(STAGE1_CFLAGS)" MAKEINFO="$(MAKEINFO)" \
- MAKEINFOFLAGS="$(MAKEINFOFLAGS)" COVERAGE_FLAGS= \
- OBJS-onestep="$(OBJS)"
+ CFLAGS="$(STAGE1_CFLAGS) $(STAGE1_CHECKING_CFLAGS)" \
+ MAKEINFO="$(MAKEINFO)" MAKEINFOFLAGS="$(MAKEINFOFLAGS)" \
+ COVERAGE_FLAGS= OBJS-onestep="$(OBJS)"
$(STAMP) stage1_build
echo stage1_build > stage_last
@@ -3481,7 +4304,7 @@ bootstrap4 bootstrap4-lean: stage4_build
unstage1 unstage2 unstage3 unstage4 unstageprofile unstagefeedback:
-set -vx; stage=`echo $@ | sed -e 's/un//'`; \
rm -f $$stage/as$(exeext); \
- rm -f $$stage/ld$(exeext); \
+ rm -f $$stage/nm$(exeext); \
rm -f $$stage/collect-ld$(exeext); \
if test -d $$stage; then \
mv $$stage/specs $(SPECS) 2>/dev/null || :; \
@@ -3536,12 +4359,19 @@ bubblestrap:
$(MAKE) $(REMAKEFLAGS) stage4_build || exit 1; \
fi
+BOOTSTRAPPING := $(shell if test -f ../stage_last; then echo yes; else echo no; fi)
+ifeq ($(BOOTSTRAPPING),yes)
+# Provide quickstrap as a target that people can type into the gcc directory,
+# and that fails if you're not into it.
+quickstrap: all
+else
quickstrap:
if test -f stage_last ; then \
LAST=`cat stage_last`; rm $$LAST; $(MAKE) $(REMAKEFLAGS) $$LAST; \
else \
$(MAKE) $(REMAKEFLAGS) stage1_build; \
fi
+endif
cleanstrap:
-$(MAKE) clean
@@ -3573,24 +4403,38 @@ fastcompare fastcompare3 fastcompare4 fastcompare-lean fastcompare3-lean fastcom
gnucompare gnucompare3 gnucompare4 gnucompare-lean gnucompare3-lean gnucompare4-lean: force
-rm -f .bad_compare
case "$@" in *compare | *compare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^[a-z]*compare\([0-9][0-9]*\).*,\1,'` ;; esac; \
- for dir in . $(SUBDIRS); do \
+ for dir in . $(SUBDIRS) libgcc; do \
if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \
for file in $$dir/*$(objext); do \
case "$@" in \
slowcompare* ) \
- tail +16c ./$$file > tmp-foo1; \
- tail +16c stage$$stage/$$file > tmp-foo2 \
- && (cmp tmp-foo1 tmp-foo2 > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
+ if tail -c +1 </dev/null >/dev/null 2>&1; then \
+ skip16='-c +17'; \
+ else \
+ skip16='+17c'; \
+ fi; \
+ tail $$skip16 ./$$file > tmp-foo1; \
+ tail $$skip16 stage$$stage/$$file > tmp-foo2; \
+ cmp tmp-foo1 tmp-foo2 > /dev/null 2>&1; \
+ cmpret=$$?; \
;; \
fastcompare* ) \
cmp $$file stage$$stage/$$file 16 16 > /dev/null 2>&1; \
- test $$? -eq 1 && echo $$file differs >> .bad_compare || true; \
+ cmpret=$$?; \
;; \
gnucompare* ) \
cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1; \
- test $$? -eq 1 && echo $$file differs >> .bad_compare || true; \
+ cmpret=$$?; \
;; \
esac ; \
+ if test $$cmpret -eq 1; then \
+ case $$file in \
+ ./cc*-checksum$(objext) | libgcc/* ) \
+ echo warning: $$file differs;; \
+ *) \
+ echo $$file differs >> .bad_compare;; \
+ esac ; \
+ fi; \
done; \
else true; fi; \
done
@@ -3623,17 +4467,19 @@ stage1-start:
do \
if [ -d stage1/$$dir ] ; then true ; else mkdir stage1/$$dir ; fi ; \
done
+ -rm -f stage1/libgcc.a stage1/libgcc_eh.a stage1/libgcov.a
+ -rm -f stage1/libgcc_s*$(SHLIB_EXT)
+ -rm -f stage1/libunwind.a stage1/libunwind*$(SHLIB_EXT)
# If SPECS is overridden, make sure it is `installed' as specs.
-mv $(SPECS) stage1/specs
- -mv $(STAGESTUFF) stage1
+ -mv $(STAGEMOVESTUFF) stage1
+ -mv build/* stage1/build
+ -cp -p $(STAGECOPYSTUFF) stage1
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then (cd stage1 && $(LN_S) ../as$(exeext) .) ; else true ; fi
-if [ -f ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-if [ -f collect-ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
- -rm -f stage1/libgcc.a stage1/libgcc_eh.a stage1/libgcov.a
- -rm -f stage1/libgcc_s*$(SHLIB_EXT)
- -rm -f stage1/libunwind.a stage1/libunwind*$(SHLIB_EXT)
-cp libgcc.a stage1
-$(RANLIB_FOR_TARGET) stage1/libgcc.a
-cp libgcov.a stage1
@@ -3660,17 +4506,19 @@ stage2-start:
do \
if [ -d stage2/$$dir ] ; then true ; else mkdir stage2/$$dir ; fi ; \
done
+ -rm -f stage2/libgcc.a stage2/libgcov.a stage2/libgcc_eh.a
+ -rm -f stage2/libgcc_s*$(SHLIB_EXT)
+ -rm -f stage2/libunwind.a stage2/libunwind*$(SHLIB_EXT)
# If SPECS is overridden, make sure it is `installed' as specs.
-mv $(SPECS) stage2/specs
- -mv $(STAGESTUFF) stage2
+ -mv $(STAGEMOVESTUFF) stage2
+ -mv build/* stage2/build
+ -cp -p $(STAGECOPYSTUFF) stage2
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then (cd stage2 && $(LN_S) ../as$(exeext) .) ; else true ; fi
-if [ -f ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-if [ -f collect-ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
- -rm -f stage2/libgcc.a stage2/libgcov.a stage2/libgcc_eh.a
- -rm -f stage2/libgcc_s*$(SHLIB_EXT)
- -rm -f stage2/libunwind.a stage2/libunwind*$(SHLIB_EXT)
-cp libgcc.a stage2
-$(RANLIB_FOR_TARGET) stage2/libgcc.a
-cp libgcov.a stage2
@@ -3693,17 +4541,19 @@ stage3-start:
do \
if [ -d stage3/$$dir ] ; then true ; else mkdir stage3/$$dir ; fi ; \
done
+ -rm -f stage3/libgcc.a stage3/libgcov.a stage3/libgcc_eh.a
+ -rm -f stage3/libgcc_s*$(SHLIB_EXT)
+ -rm -f stage3/libunwind.a stage3/libunwind*$(SHLIB_EXT)
# If SPECS is overridden, make sure it is `installed' as specs.
-mv $(SPECS) stage3/specs
- -mv $(STAGESTUFF) stage3
+ -mv $(STAGEMOVESTUFF) stage3
+ -mv build/* stage3/build
+ -cp -p $(STAGECOPYSTUFF) stage3
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then (cd stage3 && $(LN_S) ../as$(exeext) .) ; else true ; fi
-if [ -f ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-if [ -f collect-ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
- -rm -f stage3/libgcc.a stage3/libgcov.a stage3/libgcc_eh.a
- -rm -f stage3/libgcc_s*$(SHLIB_EXT)
- -rm -f stage3/libunwind.a stage3/libunwind*$(SHLIB_EXT)
-cp libgcc.a stage3
-$(RANLIB_FOR_TARGET) stage3/libgcc.a
-cp libgcov.a stage3
@@ -3726,17 +4576,19 @@ stage4-start:
do \
if [ -d stage4/$$dir ] ; then true ; else mkdir stage4/$$dir ; fi ; \
done
+ -rm -f stage4/libgcc.a stage4/libgcov.a stage4/libgcc_eh.a
+ -rm -f stage4/libgcc_s*$(SHLIB_EXT)
+ -rm -f stage4/libunwind.a stage4/libunwind*$(SHLIB_EXT)
# If SPECS is overridden, make sure it is `installed' as specs.
-mv $(SPECS) stage4/specs
- -mv $(STAGESTUFF) stage4
+ -mv $(STAGEMOVESTUFF) stage4
+ -mv build/* stage4/build
+ -cp -p $(STAGECOPYSTUFF) stage4
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then (cd stage4 && $(LN_S) ../as$(exeext) .) ; else true ; fi
-if [ -f ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-if [ -f collect-ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
- -rm -f stage4/libgcc.a stage4/libgcov.a stage4/libgcc_eh.a
- -rm -f stage4/libgcc_s*$(SHLIB_EXT)
- -rm -f stage4/libunwind.a stage4/libunwind*$(SHLIB_EXT)
-cp libgcc.a stage4
-$(RANLIB_FOR_TARGET) stage4/libgcc.a
-cp libgcov.a stage4
@@ -3759,15 +4611,17 @@ stageprofile-start:
do \
if [ -d stageprofile/$$dir ] ; then true ; else mkdir stageprofile/$$dir ; fi ; \
done
- -mv $(STAGESTUFF) stageprofile
+ -rm -f stageprofile/libgcc.a stageprofile/libgcov.a stageprofile/libgcc_eh.a
+ -rm -f stageprofile/libgcc_s*$(SHLIB_EXT)
+ -rm -f stageprofile/libunwind.a stageprofile/libunwind*$(SHLIB_EXT)
+ -mv $(STAGEMOVESTUFF) stageprofile
+ -mv build/* stageprofile/build
+ -cp -p $(STAGECOPYSTUFF) stageprofile
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then (cd stageprofile && $(LN_S) ../as$(exeext) .) ; else true ; fi
-if [ -f ld$(exeext) ] ; then (cd stageprofile && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-if [ -f collect-ld$(exeext) ] ; then (cd stageprofile && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
- -rm -f stageprofile/libgcc.a stageprofile/libgcov.a stageprofile/libgcc_eh.a
- -rm -f stageprofile/libgcc_s*$(SHLIB_EXT)
- -rm -f stageprofile/libunwind.a stageprofile/libunwind*$(SHLIB_EXT)
-cp libgcc.a stageprofile
-$(RANLIB_FOR_TARGET) stageprofile/libgcc.a
-cp libgcov.a stageprofile
@@ -3790,16 +4644,18 @@ stagefeedback-start:
do \
if [ -d stagefeedback/$$dir ] ; then true ; else mkdir stagefeedback/$$dir ; fi ; \
done
- -mv $(STAGESTUFF) stagefeedback
+ -rm -f stagefeedback/libgcc.a stagefeedback/libgcov.a stagefeedback/libgcc_eh.a
+ -rm -f stagefeedback/libgcc_s*$(SHLIB_EXT)
+ -rm -f stagefeedback/libunwind.a stagefeedback/libunwind*$(SHLIB_EXT)
+ -rm -f *.da
+ -mv $(STAGEMOVESTUFF) stagefeedback
+ -mv build/* stagefeedback/build
+ -cp -p $(STAGECOPYSTUFF) stagefeedback
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then (cd stagefeedback && $(LN_S) ../as$(exeext) .) ; else true ; fi
-if [ -f ld$(exeext) ] ; then (cd stagefeedback && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-if [ -f collect-ld$(exeext) ] ; then (cd stagefeedback && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
- -rm -f stagefeedback/libgcc.a stagefeedback/libgcov.a stagefeedback/libgcc_eh.a
- -rm -f stagefeedback/libgcc_s*$(SHLIB_EXT)
- -rm -f stagefeedback/libunwind.a stagefeedback/libunwind*$(SHLIB_EXT)
- -rm -f *.da
-for dir in fixinc po testsuite $(SUBDIRS); \
do \
rm -f $$dir/*.da ; \
@@ -3847,9 +4703,7 @@ risky-stage4: stage4
XGETTEXT = @XGETTEXT@
GMSGFMT = @GMSGFMT@
MSGMERGE = msgmerge
-
-PACKAGE = @PACKAGE@
-CATALOGS = @CATALOGS@
+CATALOGS = $(patsubst %,po/%,@CATALOGS@)
.PHONY: build- install- build-po install-po update-po
@@ -3872,20 +4726,20 @@ update-po: $(CATALOGS:.gmo=.pox)
# The new .po has to be gone over by hand, so we deposit it into
# build/po with a different extension.
-# If build/po/$(PACKAGE).pot exists, use it (it was just created),
+# If build/po/gcc.pot exists, use it (it was just created),
# else use the one in srcdir.
.po.pox:
-test -d po || mkdir po
- $(MSGMERGE) $< `if test -f po/$(PACKAGE).pot; \
- then echo po/$(PACKAGE).pot; \
- else echo $(srcdir)/po/$(PACKAGE).pot; fi` -o $@
+ $(MSGMERGE) $< `if test -f po/gcc.pot; \
+ then echo po/gcc.pot; \
+ else echo $(srcdir)/po/gcc.pot; fi` -o $@
# This rule has to look for .gmo modules in both srcdir and
# the cwd, and has to check that we actually have a catalog
# for each language, in case they weren't built or included
# with the distribution.
install-po:
- $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(datadir)
+ $(mkinstalldirs) $(DESTDIR)$(datadir)
cats="$(CATALOGS)"; for cat in $$cats; do \
lang=`basename $$cat | sed 's/\.gmo$$//'`; \
if [ -f $$cat ]; then :; \
@@ -3893,10 +4747,10 @@ install-po:
else continue; \
fi; \
dir=$(localedir)/$$lang/LC_MESSAGES; \
- echo $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$$dir; \
- $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$$dir || exit 1; \
- echo $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \
- $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \
+ echo $(mkinstalldirs) $(DESTDIR)$$dir; \
+ $(mkinstalldirs) $(DESTDIR)$$dir || exit 1; \
+ echo $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/gcc.mo; \
+ $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/gcc.mo; \
done
# Rule for regenerating the message template (gcc.pot).
@@ -3906,9 +4760,9 @@ install-po:
# Note that exgettext has an awk script embedded in it which requires a
# fairly modern (POSIX-compliant) awk.
# The .pot file is left in the build directory.
-$(PACKAGE).pot: po/$(PACKAGE).pot
-po/$(PACKAGE).pot: force options.c
+gcc.pot: po/gcc.pot
+po/gcc.pot: force
-test -d po || mkdir po
$(MAKE) srcextra
AWK=$(AWK) $(SHELL) $(srcdir)/po/exgettext \
- $(XGETTEXT) $(PACKAGE) $(srcdir)
+ $(XGETTEXT) gcc $(srcdir)
diff --git a/contrib/gcc/builtins.c b/contrib/gcc/builtins.c
index 2931684..27f1989 100644
--- a/contrib/gcc/builtins.c
+++ b/contrib/gcc/builtins.c
@@ -1,6 +1,6 @@
/* Expand builtin functions.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -27,6 +27,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "real.h"
#include "rtl.h"
#include "tree.h"
+#include "tree-gimple.h"
#include "flags.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -44,17 +45,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h"
#include "target.h"
#include "langhooks.h"
-
-#define CALLED_AS_BUILT_IN(NODE) \
- (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
-
-/* Register mappings for target machines without register windows. */
-#ifndef INCOMING_REGNO
-#define INCOMING_REGNO(OUT) (OUT)
-#endif
-#ifndef OUTGOING_REGNO
-#define OUTGOING_REGNO(IN) (IN)
-#endif
+#include "basic-block.h"
+#include "tree-mudflap.h"
#ifndef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
@@ -64,8 +56,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
const char *const built_in_class_names[4]
= {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
-#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM) #X,
-const char *const built_in_names[(int) END_BUILTINS] =
+#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
+const char * built_in_names[(int) END_BUILTINS] =
{
#include "builtins.def"
};
@@ -76,22 +68,20 @@ const char *const built_in_names[(int) END_BUILTINS] =
tree built_in_decls[(int) END_BUILTINS];
/* Declarations used when constructing the builtin implicitly in the compiler.
It may be NULL_TREE when this is invalid (for instance runtime is not
- required to implement the function call in all cases. */
+ required to implement the function call in all cases). */
tree implicit_built_in_decls[(int) END_BUILTINS];
static int get_pointer_alignment (tree, unsigned int);
-static tree c_strlen (tree, int);
static const char *c_getstr (tree);
static rtx c_readstr (const char *, enum machine_mode);
static int target_char_cast (tree, char *);
-static rtx get_memory_rtx (tree);
-static tree build_string_literal (int, const char *);
+static rtx get_memory_rtx (tree, tree);
static int apply_args_size (void);
static int apply_result_size (void);
#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
static rtx result_vector (int, rtx);
#endif
-static rtx expand_builtin_setjmp (tree, rtx);
+static void expand_builtin_update_setjmp_buf (rtx);
static void expand_builtin_prefetch (tree);
static rtx expand_builtin_apply_args (void);
static rtx expand_builtin_apply_args_1 (void);
@@ -102,9 +92,11 @@ static rtx expand_builtin_classify_type (tree);
static void expand_errno_check (tree, rtx);
static rtx expand_builtin_mathfn (tree, rtx, rtx);
static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
-static rtx expand_builtin_constant_p (tree, enum machine_mode);
+static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
+static rtx expand_builtin_sincos (tree);
+static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
static rtx expand_builtin_args_info (tree);
-static rtx expand_builtin_next_arg (tree);
+static rtx expand_builtin_next_arg (void);
static rtx expand_builtin_va_start (tree);
static rtx expand_builtin_va_end (tree);
static rtx expand_builtin_va_copy (tree);
@@ -112,27 +104,27 @@ static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
-static rtx expand_builtin_strcat (tree, rtx, enum machine_mode);
+static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
-static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode, int);
-static rtx expand_builtin_memmove (tree, rtx, enum machine_mode);
+static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
+static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
static rtx expand_builtin_bcopy (tree);
-static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
+static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
-static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
+static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
static rtx expand_builtin_bzero (tree);
static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
-static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
-static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
-static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
-static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
+static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
+static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
+static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
+static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_alloca (tree, rtx);
static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
static rtx expand_builtin_frame_address (tree, tree);
@@ -144,27 +136,88 @@ static tree stabilize_va_list (tree, int);
static rtx expand_builtin_expect (tree, rtx);
static tree fold_builtin_constant_p (tree);
static tree fold_builtin_classify_type (tree);
+static tree fold_builtin_strlen (tree);
static tree fold_builtin_inf (tree, int);
static tree fold_builtin_nan (tree, tree, int);
static int validate_arglist (tree, ...);
static bool integer_valued_real_p (tree);
-static tree fold_trunc_transparent_mathfn (tree);
+static tree fold_trunc_transparent_mathfn (tree, tree);
static bool readonly_data_expr (tree);
static rtx expand_builtin_fabs (tree, rtx, rtx);
-static rtx expand_builtin_cabs (tree, rtx);
-static tree fold_builtin_cabs (tree, tree, tree);
-static tree fold_builtin_trunc (tree);
-static tree fold_builtin_floor (tree);
-static tree fold_builtin_ceil (tree);
-static tree fold_builtin_bitop (tree);
-static tree fold_builtin_memcpy (tree);
-static tree fold_builtin_mempcpy (tree);
-static tree fold_builtin_memmove (tree);
-static tree fold_builtin_strcpy (tree);
-static tree fold_builtin_strncpy (tree);
+static rtx expand_builtin_signbit (tree, rtx);
+static tree fold_builtin_sqrt (tree, tree);
+static tree fold_builtin_cbrt (tree, tree);
+static tree fold_builtin_pow (tree, tree, tree);
+static tree fold_builtin_powi (tree, tree, tree);
+static tree fold_builtin_sin (tree);
+static tree fold_builtin_cos (tree, tree, tree);
+static tree fold_builtin_tan (tree);
+static tree fold_builtin_atan (tree, tree);
+static tree fold_builtin_trunc (tree, tree);
+static tree fold_builtin_floor (tree, tree);
+static tree fold_builtin_ceil (tree, tree);
+static tree fold_builtin_round (tree, tree);
+static tree fold_builtin_int_roundingfn (tree, tree);
+static tree fold_builtin_bitop (tree, tree);
+static tree fold_builtin_memory_op (tree, tree, bool, int);
+static tree fold_builtin_strchr (tree, tree);
static tree fold_builtin_memcmp (tree);
static tree fold_builtin_strcmp (tree);
static tree fold_builtin_strncmp (tree);
+static tree fold_builtin_signbit (tree, tree);
+static tree fold_builtin_copysign (tree, tree, tree);
+static tree fold_builtin_isascii (tree);
+static tree fold_builtin_toascii (tree);
+static tree fold_builtin_isdigit (tree);
+static tree fold_builtin_fabs (tree, tree);
+static tree fold_builtin_abs (tree, tree);
+static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
+ enum tree_code);
+static tree fold_builtin_1 (tree, tree, bool);
+
+static tree fold_builtin_strpbrk (tree, tree);
+static tree fold_builtin_strstr (tree, tree);
+static tree fold_builtin_strrchr (tree, tree);
+static tree fold_builtin_strcat (tree);
+static tree fold_builtin_strncat (tree);
+static tree fold_builtin_strspn (tree);
+static tree fold_builtin_strcspn (tree);
+static tree fold_builtin_sprintf (tree, int);
+
+static rtx expand_builtin_object_size (tree);
+static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
+ enum built_in_function);
+static void maybe_emit_chk_warning (tree, enum built_in_function);
+static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
+static tree fold_builtin_object_size (tree);
+static tree fold_builtin_strcat_chk (tree, tree);
+static tree fold_builtin_strncat_chk (tree, tree);
+static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
+static tree fold_builtin_printf (tree, tree, bool, enum built_in_function);
+static tree fold_builtin_fprintf (tree, tree, bool, enum built_in_function);
+static bool init_target_chars (void);
+
+static unsigned HOST_WIDE_INT target_newline;
+static unsigned HOST_WIDE_INT target_percent;
+static unsigned HOST_WIDE_INT target_c;
+static unsigned HOST_WIDE_INT target_s;
+static char target_percent_c[3];
+static char target_percent_s[3];
+static char target_percent_s_newline[4];
+
+/* Return true if NODE should be considered for inline expansion regardless
+ of the optimization level. This means whenever a function is invoked with
+ its "internal" name, which normally contains the prefix "__builtin". */
+
+static bool called_as_built_in (tree node)
+{
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
+ if (strncmp (name, "__builtin_", 10) == 0)
+ return true;
+ if (strncmp (name, "__sync_", 7) == 0)
+ return true;
+ return false;
+}
/* Return the alignment in bits of EXP, a pointer valued expression.
But don't return more than MAX_ALIGN no matter what.
@@ -179,7 +232,11 @@ get_pointer_alignment (tree exp, unsigned int max_align)
{
unsigned int align, inner;
- if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
+ /* We rely on TER to compute accurate alignment information. */
+ if (!(optimize && flag_tree_ter))
+ return 0;
+
+ if (!POINTER_TYPE_P (TREE_TYPE (exp)))
return 0;
align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
@@ -193,7 +250,7 @@ get_pointer_alignment (tree exp, unsigned int max_align)
case CONVERT_EXPR:
case NON_LVALUE_EXPR:
exp = TREE_OPERAND (exp, 0);
- if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
+ if (! POINTER_TYPE_P (TREE_TYPE (exp)))
return align;
inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
@@ -218,14 +275,59 @@ get_pointer_alignment (tree exp, unsigned int max_align)
case ADDR_EXPR:
/* See what we are pointing at and look at its alignment. */
exp = TREE_OPERAND (exp, 0);
+ inner = max_align;
+ if (handled_component_p (exp))
+ {
+ HOST_WIDE_INT bitsize, bitpos;
+ tree offset;
+ enum machine_mode mode;
+ int unsignedp, volatilep;
+
+ exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
+ &mode, &unsignedp, &volatilep, true);
+ if (bitpos)
+ inner = MIN (inner, (unsigned) (bitpos & -bitpos));
+ if (offset && TREE_CODE (offset) == PLUS_EXPR
+ && host_integerp (TREE_OPERAND (offset, 1), 1))
+ {
+ /* Any overflow in calculating offset_bits won't change
+ the alignment. */
+ unsigned offset_bits
+ = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
+ * BITS_PER_UNIT);
+
+ if (offset_bits)
+ inner = MIN (inner, (offset_bits & -offset_bits));
+ offset = TREE_OPERAND (offset, 0);
+ }
+ if (offset && TREE_CODE (offset) == MULT_EXPR
+ && host_integerp (TREE_OPERAND (offset, 1), 1))
+ {
+ /* Any overflow in calculating offset_factor won't change
+ the alignment. */
+ unsigned offset_factor
+ = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
+ * BITS_PER_UNIT);
+
+ if (offset_factor)
+ inner = MIN (inner, (offset_factor & -offset_factor));
+ }
+ else if (offset)
+ inner = MIN (inner, BITS_PER_UNIT);
+ }
if (TREE_CODE (exp) == FUNCTION_DECL)
align = FUNCTION_BOUNDARY;
else if (DECL_P (exp))
- align = DECL_ALIGN (exp);
+ align = MIN (inner, DECL_ALIGN (exp));
#ifdef CONSTANT_ALIGNMENT
- else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
- align = CONSTANT_ALIGNMENT (exp, align);
+ else if (CONSTANT_CLASS_P (exp))
+ align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
#endif
+ else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
+ || TREE_CODE (exp) == INDIRECT_REF)
+ align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
+ else
+ align = MIN (align, inner);
return MIN (align, max_align);
default:
@@ -250,7 +352,7 @@ get_pointer_alignment (tree exp, unsigned int max_align)
Unfortunately, string_constant can't access the values of const char
arrays with initializers, so neither can we do so here. */
-static tree
+tree
c_strlen (tree src, int only_value)
{
tree offset_node;
@@ -266,7 +368,7 @@ c_strlen (tree src, int only_value)
len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
- if (tree_int_cst_equal (len1, len2))
+ if (tree_int_cst_equal (len1, len2))
return len1;
}
@@ -315,7 +417,7 @@ c_strlen (tree src, int only_value)
runtime. */
if (offset < 0 || offset > max)
{
- warning ("offset outside bounds of constant string");
+ warning (0, "offset outside bounds of constant string");
return 0;
}
@@ -359,8 +461,8 @@ c_readstr (const char *str, enum machine_mode mode)
HOST_WIDE_INT ch;
unsigned int i, j;
- if (GET_MODE_CLASS (mode) != MODE_INT)
- abort ();
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
+
c[0] = 0;
c[1] = 0;
ch = 1;
@@ -373,8 +475,8 @@ c_readstr (const char *str, enum machine_mode mode)
&& GET_MODE_SIZE (mode) > UNITS_PER_WORD)
j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
j *= BITS_PER_UNIT;
- if (j > 2 * HOST_BITS_PER_WIDE_INT)
- abort ();
+ gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
+
if (ch)
ch = (unsigned char) str[i];
c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
@@ -383,7 +485,7 @@ c_readstr (const char *str, enum machine_mode mode)
}
/* Cast a target constant CST to target CHAR and if that value fits into
- host char type, return zero and put that value into variable pointed by
+ host char type, return zero and put that value into variable pointed to by
P. */
static int
@@ -410,25 +512,64 @@ target_char_cast (tree cst, char *p)
return 0;
}
+/* Similar to save_expr, but assumes that arbitrary code is not executed
+ in between the multiple evaluations. In particular, we assume that a
+ non-addressable local variable will not be modified. */
+
+static tree
+builtin_save_expr (tree exp)
+{
+ if (TREE_ADDRESSABLE (exp) == 0
+ && (TREE_CODE (exp) == PARM_DECL
+ || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
+ return exp;
+
+ return save_expr (exp);
+}
+
/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
times to get the address of either a higher stack frame, or a return
address located within it (depending on FNDECL_CODE). */
-rtx
-expand_builtin_return_addr (enum built_in_function fndecl_code, int count,
- rtx tem)
+static rtx
+expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
{
int i;
+#ifdef INITIAL_FRAME_ADDRESS_RTX
+ rtx tem = INITIAL_FRAME_ADDRESS_RTX;
+#else
+ rtx tem;
+
+ /* For a zero count with __builtin_return_address, we don't care what
+ frame address we return, because target-specific definitions will
+ override us. Therefore frame pointer elimination is OK, and using
+ the soft frame pointer is OK.
+
+ For a non-zero count, or a zero count with __builtin_frame_address,
+ we require a stable offset from the current frame pointer to the
+ previous one, so we must use the hard frame pointer, and
+ we must disable frame pointer elimination. */
+ if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
+ tem = frame_pointer_rtx;
+ else
+ {
+ tem = hard_frame_pointer_rtx;
+
+ /* Tell reload not to eliminate the frame pointer. */
+ current_function_accesses_prior_frames = 1;
+ }
+#endif
+
/* Some machines need special handling before we can access
- arbitrary frames. For example, on the sparc, we must first flush
+ arbitrary frames. For example, on the SPARC, we must first flush
all register windows to the stack. */
#ifdef SETUP_FRAME_ADDRESSES
if (count > 0)
SETUP_FRAME_ADDRESSES ();
#endif
- /* On the sparc, the return address is not in the frame, it is in a
+ /* On the SPARC, the return address is not in the frame, it is in a
register. There is no way to access it off of the current frame
pointer, but it can be accessed off the previous frame pointer by
reading the value from the register window save area. */
@@ -446,24 +587,26 @@ expand_builtin_return_addr (enum built_in_function fndecl_code, int count,
tem = DYNAMIC_CHAIN_ADDRESS (tem);
#endif
tem = memory_address (Pmode, tem);
- tem = gen_rtx_MEM (Pmode, tem);
- set_mem_alias_set (tem, get_frame_alias_set ());
+ tem = gen_frame_mem (Pmode, tem);
tem = copy_to_reg (tem);
}
- /* For __builtin_frame_address, return what we've got. */
+ /* For __builtin_frame_address, return what we've got. But, on
+ the SPARC for example, we may have to add a bias. */
if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
+#ifdef FRAME_ADDR_RTX
+ return FRAME_ADDR_RTX (tem);
+#else
return tem;
+#endif
- /* For __builtin_return_address, Get the return address from that
- frame. */
+ /* For __builtin_return_address, get the return address from that frame. */
#ifdef RETURN_ADDR_RTX
tem = RETURN_ADDR_RTX (count, tem);
#else
tem = memory_address (Pmode,
plus_constant (tem, GET_MODE_SIZE (Pmode)));
- tem = gen_rtx_MEM (Pmode, tem);
- set_mem_alias_set (tem, get_frame_alias_set ());
+ tem = gen_frame_mem (Pmode, tem);
#endif
return tem;
}
@@ -472,8 +615,8 @@ expand_builtin_return_addr (enum built_in_function fndecl_code, int count,
static HOST_WIDE_INT setjmp_alias_set = -1;
/* Construct the leading half of a __builtin_setjmp call. Control will
- return to RECEIVER_LABEL. This is used directly by sjlj exception
- handling code. */
+ return to RECEIVER_LABEL. This is also called directly by the SJLJ
+ exception handling code. */
void
expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
@@ -489,19 +632,13 @@ expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
- emit_queue ();
-
/* We store the frame pointer and the address of receiver_label in
the buffer and use the rest of it for the stack save area, which
is machine-dependent. */
-#ifndef BUILTIN_SETJMP_FRAME_VALUE
-#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
-#endif
-
mem = gen_rtx_MEM (Pmode, buf_addr);
set_mem_alias_set (mem, setjmp_alias_set);
- emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
+ emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
set_mem_alias_set (mem, setjmp_alias_set);
@@ -530,8 +667,8 @@ expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
current_function_has_nonlocal_label = 1;
}
-/* Construct the trailing part of a __builtin_setjmp call.
- This is used directly by sjlj exception handling code. */
+/* Construct the trailing part of a __builtin_setjmp call. This is
+ also called directly by the SJLJ exception handling code. */
void
expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
@@ -545,12 +682,16 @@ expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
/* Now put in the code to restore the frame pointer, and argument
- pointer, if needed. The code below is from expand_end_bindings
- in stmt.c; see detailed documentation there. */
+ pointer, if needed. */
#ifdef HAVE_nonlocal_goto
if (! HAVE_nonlocal_goto)
#endif
- emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
+ {
+ emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
+ /* This might change the hard frame pointer in ways that aren't
+ apparent to early optimization passes, so force a clobber. */
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, hard_frame_pointer_rtx));
+ }
#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
if (fixed_regs[ARG_POINTER_REGNUM])
@@ -595,69 +736,12 @@ expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
}
-/* __builtin_setjmp is passed a pointer to an array of five words (not
- all will be used on all machines). It operates similarly to the C
- library function of the same name, but is more efficient. Much of
- the code below (and for longjmp) is copied from the handling of
- non-local gotos.
-
- NOTE: This is intended for use by GNAT and the exception handling
- scheme in the compiler and will only work in the method used by
- them. */
-
-static rtx
-expand_builtin_setjmp (tree arglist, rtx target)
-{
- rtx buf_addr, next_lab, cont_lab;
-
- if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
- return NULL_RTX;
-
- if (target == 0 || GET_CODE (target) != REG
- || REGNO (target) < FIRST_PSEUDO_REGISTER)
- target = gen_reg_rtx (TYPE_MODE (integer_type_node));
-
- buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
-
- next_lab = gen_label_rtx ();
- cont_lab = gen_label_rtx ();
-
- expand_builtin_setjmp_setup (buf_addr, next_lab);
-
- /* Set TARGET to zero and branch to the continue label. Use emit_jump to
- ensure that pending stack adjustments are flushed. */
- emit_move_insn (target, const0_rtx);
- emit_jump (cont_lab);
-
- emit_label (next_lab);
-
- expand_builtin_setjmp_receiver (next_lab);
-
- /* Set TARGET to one. */
- emit_move_insn (target, const1_rtx);
- emit_label (cont_lab);
-
- /* Tell flow about the strange goings on. Putting `next_lab' on
- `nonlocal_goto_handler_labels' to indicates that function
- calls may traverse the arc back to this label. */
-
- current_function_has_nonlocal_label = 1;
- nonlocal_goto_handler_labels
- = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
-
- return target;
-}
-
/* __builtin_longjmp is passed a pointer to an array of five words (not
all will be used on all machines). It operates similarly to the C
library function of the same name, but is more efficient. Much of
- the code below is copied from the handling of non-local gotos.
-
- NOTE: This is intended for use by GNAT and the exception handling
- scheme in the compiler and will only work in the method used by
- them. */
+ the code below is copied from the handling of non-local gotos. */
-void
+static void
expand_builtin_longjmp (rtx buf_addr, rtx value)
{
rtx fp, lab, stack, insn, last;
@@ -675,10 +759,7 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
a second argument of 1, because that is what builtin_setjmp will
return. This also makes EH slightly more efficient, since we are no
longer copying around a value that we don't care about. */
- if (value != const1_rtx)
- abort ();
-
- current_function_calls_longjmp = 1;
+ gcc_assert (value == const1_rtx);
last = get_last_insn ();
#ifdef HAVE_builtin_longjmp
@@ -699,7 +780,7 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
/* Pick up FP, label, and SP from the block and jump. This code is
from expand_goto in stmt.c; see there for detailed comments. */
-#if HAVE_nonlocal_goto
+#ifdef HAVE_nonlocal_goto
if (HAVE_nonlocal_goto)
/* We have to pass a value to the nonlocal_goto pattern that will
get copied into the static_chain pointer, but it does not matter
@@ -733,19 +814,128 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
internal exception handling use only. */
for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
{
- if (insn == last)
- abort ();
- if (GET_CODE (insn) == JUMP_INSN)
+ gcc_assert (insn != last);
+
+ if (JUMP_P (insn))
{
REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
REG_NOTES (insn));
break;
}
- else if (GET_CODE (insn) == CALL_INSN)
+ else if (CALL_P (insn))
break;
}
}
+/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
+ and the address of the save area. */
+
+static rtx
+expand_builtin_nonlocal_goto (tree arglist)
+{
+ tree t_label, t_save_area;
+ rtx r_label, r_save_area, r_fp, r_sp, insn;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return NULL_RTX;
+
+ t_label = TREE_VALUE (arglist);
+ arglist = TREE_CHAIN (arglist);
+ t_save_area = TREE_VALUE (arglist);
+
+ r_label = expand_normal (t_label);
+ r_label = convert_memory_address (Pmode, r_label);
+ r_save_area = expand_normal (t_save_area);
+ r_save_area = convert_memory_address (Pmode, r_save_area);
+ r_fp = gen_rtx_MEM (Pmode, r_save_area);
+ r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
+ plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
+
+ current_function_has_nonlocal_goto = 1;
+
+#ifdef HAVE_nonlocal_goto
+ /* ??? We no longer need to pass the static chain value, afaik. */
+ if (HAVE_nonlocal_goto)
+ emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
+ else
+#endif
+ {
+ r_label = copy_to_reg (r_label);
+
+ emit_insn (gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM (BLKmode,
+ gen_rtx_SCRATCH (VOIDmode))));
+
+ emit_insn (gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM (BLKmode,
+ hard_frame_pointer_rtx)));
+
+ /* Restore frame pointer for containing function.
+ This sets the actual hard register used for the frame pointer
+ to the location of the function's incoming static chain info.
+ The non-local goto handler will then adjust it to contain the
+ proper value and reload the argument pointer, if needed. */
+ emit_move_insn (hard_frame_pointer_rtx, r_fp);
+ emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
+
+ /* USE of hard_frame_pointer_rtx added for consistency;
+ not clear if really needed. */
+ emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+ emit_indirect_jump (r_label);
+ }
+
+ /* Search backwards to the jump insn and mark it as a
+ non-local goto. */
+ for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+ {
+ if (JUMP_P (insn))
+ {
+ REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
+ const0_rtx, REG_NOTES (insn));
+ break;
+ }
+ else if (CALL_P (insn))
+ break;
+ }
+
+ return const0_rtx;
+}
+
+/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
+ (not all will be used on all machines) that was passed to __builtin_setjmp.
+ It updates the stack pointer in that block to correspond to the current
+ stack pointer. */
+
+static void
+expand_builtin_update_setjmp_buf (rtx buf_addr)
+{
+ enum machine_mode sa_mode = Pmode;
+ rtx stack_save;
+
+
+#ifdef HAVE_save_stack_nonlocal
+ if (HAVE_save_stack_nonlocal)
+ sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
+#endif
+#ifdef STACK_SAVEAREA_MODE
+ sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
+#endif
+
+ stack_save
+ = gen_rtx_MEM (sa_mode,
+ memory_address
+ (sa_mode,
+ plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
+
+#ifdef HAVE_setjmp
+ if (HAVE_setjmp)
+ emit_insn (gen_setjmp ());
+#endif
+
+ emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
+}
+
/* Expand a call to __builtin_prefetch. For a target that does not support
data prefetch, evaluate the memory address argument in case it has side
effects. */
@@ -769,12 +959,12 @@ expand_builtin_prefetch (tree arglist)
if (TREE_CHAIN (TREE_CHAIN (arglist)))
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
else
- arg2 = build_int_2 (3, 0);
+ arg2 = build_int_cst (NULL_TREE, 3);
}
else
{
arg1 = integer_zero_node;
- arg2 = build_int_2 (3, 0);
+ arg2 = build_int_cst (NULL_TREE, 3);
}
/* Argument 0 is an address. */
@@ -783,28 +973,29 @@ expand_builtin_prefetch (tree arglist)
/* Argument 1 (read/write flag) must be a compile-time constant int. */
if (TREE_CODE (arg1) != INTEGER_CST)
{
- error ("second arg to `__builtin_prefetch' must be a constant");
+ error ("second argument to %<__builtin_prefetch%> must be a constant");
arg1 = integer_zero_node;
}
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ op1 = expand_normal (arg1);
/* Argument 1 must be either zero or one. */
if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
{
- warning ("invalid second arg to __builtin_prefetch; using zero");
+ warning (0, "invalid second argument to %<__builtin_prefetch%>;"
+ " using zero");
op1 = const0_rtx;
}
/* Argument 2 (locality) must be a compile-time constant int. */
if (TREE_CODE (arg2) != INTEGER_CST)
{
- error ("third arg to `__builtin_prefetch' must be a constant");
+ error ("third argument to %<__builtin_prefetch%> must be a constant");
arg2 = integer_zero_node;
}
- op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ op2 = expand_normal (arg2);
/* Argument 2 must be 0, 1, 2, or 3. */
if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
{
- warning ("invalid third arg to __builtin_prefetch; using zero");
+ warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
op2 = const0_rtx;
}
@@ -821,27 +1012,24 @@ expand_builtin_prefetch (tree arglist)
}
emit_insn (gen_prefetch (op0, op1, op2));
}
- else
#endif
- op0 = protect_from_queue (op0, 0);
+
/* Don't do anything with direct references to volatile memory, but
generate code to handle other side effects. */
- if (GET_CODE (op0) != MEM && side_effects_p (op0))
+ if (!MEM_P (op0) && side_effects_p (op0))
emit_insn (op0);
}
/* Get a MEM rtx for expression EXP which is the address of an operand
- to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */
+ to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
+ the maximum length of the block of memory that might be accessed or
+ NULL if unknown. */
static rtx
-get_memory_rtx (tree exp)
+get_memory_rtx (tree exp, tree len)
{
- rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM);
- rtx mem;
-
- addr = convert_memory_address (Pmode, addr);
-
- mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
+ rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
+ rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
/* Get an expression we can use to find the attributes to assign to MEM.
If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
@@ -852,15 +1040,94 @@ get_memory_rtx (tree exp)
exp = TREE_OPERAND (exp, 0);
if (TREE_CODE (exp) == ADDR_EXPR)
- {
- exp = TREE_OPERAND (exp, 0);
- set_mem_attributes (mem, exp, 0);
- }
+ exp = TREE_OPERAND (exp, 0);
else if (POINTER_TYPE_P (TREE_TYPE (exp)))
+ exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
+ else
+ exp = NULL;
+
+ /* Honor attributes derived from exp, except for the alias set
+ (as builtin stringops may alias with anything) and the size
+ (as stringops may access multiple array elements). */
+ if (exp)
{
- exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
- /* memcpy, memset and other builtin stringops can alias with anything. */
+ set_mem_attributes (mem, exp, 0);
+
+ /* Allow the string and memory builtins to overflow from one
+ field into another, see http://gcc.gnu.org/PR23561.
+ Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
+ memory accessed by the string or memory builtin will fit
+ within the field. */
+ if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
+ {
+ tree mem_expr = MEM_EXPR (mem);
+ HOST_WIDE_INT offset = -1, length = -1;
+ tree inner = exp;
+
+ while (TREE_CODE (inner) == ARRAY_REF
+ || TREE_CODE (inner) == NOP_EXPR
+ || TREE_CODE (inner) == CONVERT_EXPR
+ || TREE_CODE (inner) == NON_LVALUE_EXPR
+ || TREE_CODE (inner) == VIEW_CONVERT_EXPR
+ || TREE_CODE (inner) == SAVE_EXPR)
+ inner = TREE_OPERAND (inner, 0);
+
+ gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
+
+ if (MEM_OFFSET (mem)
+ && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
+ offset = INTVAL (MEM_OFFSET (mem));
+
+ if (offset >= 0 && len && host_integerp (len, 0))
+ length = tree_low_cst (len, 0);
+
+ while (TREE_CODE (inner) == COMPONENT_REF)
+ {
+ tree field = TREE_OPERAND (inner, 1);
+ gcc_assert (! DECL_BIT_FIELD (field));
+ gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
+ gcc_assert (field == TREE_OPERAND (mem_expr, 1));
+
+ if (length >= 0
+ && TYPE_SIZE_UNIT (TREE_TYPE (inner))
+ && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
+ {
+ HOST_WIDE_INT size
+ = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
+ /* If we can prove the memory starting at XEXP (mem, 0)
+ and ending at XEXP (mem, 0) + LENGTH will fit into
+ this field, we can keep that COMPONENT_REF in MEM_EXPR. */
+ if (offset <= size
+ && length <= size
+ && offset + length <= size)
+ break;
+ }
+
+ if (offset >= 0
+ && host_integerp (DECL_FIELD_OFFSET (field), 0))
+ offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
+ + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+ / BITS_PER_UNIT;
+ else
+ {
+ offset = -1;
+ length = -1;
+ }
+
+ mem_expr = TREE_OPERAND (mem_expr, 0);
+ inner = TREE_OPERAND (inner, 0);
+ }
+
+ if (mem_expr == NULL)
+ offset = -1;
+ if (mem_expr != MEM_EXPR (mem))
+ {
+ set_mem_expr (mem, mem_expr);
+ set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
+ }
+ }
set_mem_alias_set (mem, 0);
+ set_mem_size (mem, NULL_RTX);
}
return mem;
@@ -888,23 +1155,6 @@ static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
used for calling a function. */
static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
-/* Return the offset of register REGNO into the block returned by
- __builtin_apply_args. This is not declared static, since it is
- needed in objc-act.c. */
-
-int
-apply_args_register_offset (int regno)
-{
- apply_args_size ();
-
- /* Arguments are always put in outgoing registers (in the argument
- block) if such make sense. */
-#ifdef OUTGOING_REGNO
- regno = OUTGOING_REGNO (regno);
-#endif
- return apply_args_reg_offset[regno];
-}
-
/* Return the size required for the block returned by __builtin_apply_args,
and initialize apply_args_mode. */
@@ -930,44 +1180,9 @@ apply_args_size (void)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (FUNCTION_ARG_REGNO_P (regno))
{
- /* Search for the proper mode for copying this register's
- value. I'm not sure this is right, but it works so far. */
- enum machine_mode best_mode = VOIDmode;
-
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_MODE_OK (regno, mode)
- && HARD_REGNO_NREGS (regno, mode) == 1)
- best_mode = mode;
-
- if (best_mode == VOIDmode)
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_MODE_OK (regno, mode)
- && have_insn_for (SET, mode))
- best_mode = mode;
-
- if (best_mode == VOIDmode)
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_MODE_OK (regno, mode)
- && have_insn_for (SET, mode))
- best_mode = mode;
-
- if (best_mode == VOIDmode)
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_MODE_OK (regno, mode)
- && have_insn_for (SET, mode))
- best_mode = mode;
-
- mode = best_mode;
- if (mode == VOIDmode)
- abort ();
+ mode = reg_raw_mode[regno];
+
+ gcc_assert (mode != VOIDmode);
align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
if (size % align != 0)
@@ -1003,43 +1218,9 @@ apply_result_size (void)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (FUNCTION_VALUE_REGNO_P (regno))
{
- /* Search for the proper mode for copying this register's
- value. I'm not sure this is right, but it works so far. */
- enum machine_mode best_mode = VOIDmode;
-
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
- mode != TImode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_MODE_OK (regno, mode))
- best_mode = mode;
-
- if (best_mode == VOIDmode)
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_MODE_OK (regno, mode)
- && have_insn_for (SET, mode))
- best_mode = mode;
-
- if (best_mode == VOIDmode)
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_MODE_OK (regno, mode)
- && have_insn_for (SET, mode))
- best_mode = mode;
-
- if (best_mode == VOIDmode)
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_MODE_OK (regno, mode)
- && have_insn_for (SET, mode))
- best_mode = mode;
-
- mode = best_mode;
- if (mode == VOIDmode)
- abort ();
+ mode = reg_raw_mode[regno];
+
+ gcc_assert (mode != VOIDmode);
align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
if (size % align != 0)
@@ -1135,7 +1316,7 @@ expand_builtin_apply_args_1 (void)
NULL_RTX);
#endif
emit_move_insn (adjust_address (registers, Pmode, 0), tem);
-
+
size = GET_MODE_SIZE (Pmode);
/* Save the structure value address unless this is passed as an
@@ -1184,7 +1365,7 @@ expand_builtin_apply_args (void)
chain current, so the code is placed at the start of the
function. */
push_topmost_sequence ();
- emit_insn_before (seq, NEXT_INSN (get_insns ()));
+ emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
pop_topmost_sequence ();
return temp;
}
@@ -1216,9 +1397,6 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
incoming_args, 0, OPTAB_LIB_WIDEN);
#endif
- /* Perform postincrements before actually calling the function. */
- emit_queue ();
-
/* Push a new argument block and copy the arguments. Do not allow
the (potential) memcpy call below to interfere with our stack
manipulations. */
@@ -1281,13 +1459,13 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
rtx value = gen_reg_rtx (Pmode);
emit_move_insn (value, adjust_address (arguments, Pmode, size));
emit_move_insn (struct_value, value);
- if (GET_CODE (struct_value) == REG)
+ if (REG_P (struct_value))
use_reg (&call_fusage, struct_value);
size += GET_MODE_SIZE (Pmode);
}
/* All arguments and registers used for the call are set up by now! */
- function = prepare_call_address (function, NULL_TREE, &call_fusage, 0, 0);
+ function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
/* Ensure address is valid. SYMBOL_REF is already valid, so no need,
and we don't want to load it into a register as an optimization,
@@ -1314,8 +1492,8 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if ((mode = apply_result_mode[regno]) != VOIDmode)
{
- if (valreg)
- abort (); /* HAVE_untyped_call required. */
+ gcc_assert (!valreg); /* HAVE_untyped_call required. */
+
valreg = gen_rtx_REG (mode, regno);
}
@@ -1327,7 +1505,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
}
else
#endif
- abort ();
+ gcc_unreachable ();
/* Find the CALL insn we just emitted, and attach the register usage
information. */
@@ -1408,7 +1586,6 @@ type_to_class (tree type)
{
case VOID_TYPE: return void_type_class;
case INTEGER_TYPE: return integer_type_class;
- case CHAR_TYPE: return char_type_class;
case ENUMERAL_TYPE: return enumeral_type_class;
case BOOLEAN_TYPE: return boolean_type_class;
case POINTER_TYPE: return pointer_type_class;
@@ -1423,8 +1600,6 @@ type_to_class (tree type)
case QUAL_UNION_TYPE: return union_type_class;
case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
? string_type_class : array_type_class);
- case SET_TYPE: return set_type_class;
- case FILE_TYPE: return file_type_class;
case LANG_TYPE: return lang_type_class;
default: return no_type_class;
}
@@ -1441,32 +1616,6 @@ expand_builtin_classify_type (tree arglist)
return GEN_INT (no_type_class);
}
-/* Expand expression EXP, which is a call to __builtin_constant_p. */
-
-static rtx
-expand_builtin_constant_p (tree arglist, enum machine_mode target_mode)
-{
- rtx tmp;
-
- if (arglist == 0)
- return const0_rtx;
- arglist = TREE_VALUE (arglist);
-
- /* We have taken care of the easy cases during constant folding. This
- case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE
- get a chance to see if it can deduce whether ARGLIST is constant.
- If CSE isn't going to run, of course, don't bother waiting. */
-
- if (cse_not_expected)
- return const0_rtx;
-
- current_function_calls_constant_p = 1;
-
- tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
- tmp = gen_rtx_CONSTANT_P_RTX (target_mode, tmp);
- return tmp;
-}
-
/* This helper macro, meant to be used in mathfn_built_in below,
determines which among a set of three builtin math functions is
appropriate for a given type mode. The `F' and `L' cases are
@@ -1481,7 +1630,6 @@ expand_builtin_constant_p (tree arglist, enum machine_mode target_mode)
tree
mathfn_built_in (tree type, enum built_in_function fn)
{
- const enum machine_mode type_mode = TYPE_MODE (type);
enum built_in_function fcode, fcodef, fcodel;
switch (fn)
@@ -1521,8 +1669,12 @@ mathfn_built_in (tree type, enum built_in_function fn)
CASE_MATHFN (BUILT_IN_J0)
CASE_MATHFN (BUILT_IN_J1)
CASE_MATHFN (BUILT_IN_JN)
+ CASE_MATHFN (BUILT_IN_LCEIL)
CASE_MATHFN (BUILT_IN_LDEXP)
+ CASE_MATHFN (BUILT_IN_LFLOOR)
CASE_MATHFN (BUILT_IN_LGAMMA)
+ CASE_MATHFN (BUILT_IN_LLCEIL)
+ CASE_MATHFN (BUILT_IN_LLFLOOR)
CASE_MATHFN (BUILT_IN_LLRINT)
CASE_MATHFN (BUILT_IN_LLROUND)
CASE_MATHFN (BUILT_IN_LOG)
@@ -1539,6 +1691,7 @@ mathfn_built_in (tree type, enum built_in_function fn)
CASE_MATHFN (BUILT_IN_NEXTAFTER)
CASE_MATHFN (BUILT_IN_NEXTTOWARD)
CASE_MATHFN (BUILT_IN_POW)
+ CASE_MATHFN (BUILT_IN_POWI)
CASE_MATHFN (BUILT_IN_POW10)
CASE_MATHFN (BUILT_IN_REMAINDER)
CASE_MATHFN (BUILT_IN_REMQUO)
@@ -1564,11 +1717,11 @@ mathfn_built_in (tree type, enum built_in_function fn)
return 0;
}
- if (type_mode == TYPE_MODE (double_type_node))
+ if (TYPE_MAIN_VARIANT (type) == double_type_node)
return implicit_built_in_decls[fcode];
- else if (type_mode == TYPE_MODE (float_type_node))
+ else if (TYPE_MAIN_VARIANT (type) == float_type_node)
return implicit_built_in_decls[fcodef];
- else if (type_mode == TYPE_MODE (long_double_type_node))
+ else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
return implicit_built_in_decls[fcodel];
else
return 0;
@@ -1613,7 +1766,7 @@ expand_errno_check (tree exp, rtx target)
}
-/* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
+/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
Return 0 if a normal call should be emitted rather than expanding the
function in-line. EXP is the expression that is a call to the builtin
function; if convenient, the result should be placed in TARGET.
@@ -1637,58 +1790,56 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
switch (DECL_FUNCTION_CODE (fndecl))
{
- case BUILT_IN_SIN:
- case BUILT_IN_SINF:
- case BUILT_IN_SINL:
- builtin_optab = sin_optab; break;
- case BUILT_IN_COS:
- case BUILT_IN_COSF:
- case BUILT_IN_COSL:
- builtin_optab = cos_optab; break;
- case BUILT_IN_SQRT:
- case BUILT_IN_SQRTF:
- case BUILT_IN_SQRTL:
+ CASE_FLT_FN (BUILT_IN_SQRT):
errno_set = ! tree_expr_nonnegative_p (arg);
builtin_optab = sqrt_optab;
break;
- case BUILT_IN_EXP:
- case BUILT_IN_EXPF:
- case BUILT_IN_EXPL:
+ CASE_FLT_FN (BUILT_IN_EXP):
errno_set = true; builtin_optab = exp_optab; break;
- case BUILT_IN_LOG:
- case BUILT_IN_LOGF:
- case BUILT_IN_LOGL:
+ CASE_FLT_FN (BUILT_IN_EXP10):
+ CASE_FLT_FN (BUILT_IN_POW10):
+ errno_set = true; builtin_optab = exp10_optab; break;
+ CASE_FLT_FN (BUILT_IN_EXP2):
+ errno_set = true; builtin_optab = exp2_optab; break;
+ CASE_FLT_FN (BUILT_IN_EXPM1):
+ errno_set = true; builtin_optab = expm1_optab; break;
+ CASE_FLT_FN (BUILT_IN_LOGB):
+ errno_set = true; builtin_optab = logb_optab; break;
+ CASE_FLT_FN (BUILT_IN_ILOGB):
+ errno_set = true; builtin_optab = ilogb_optab; break;
+ CASE_FLT_FN (BUILT_IN_LOG):
errno_set = true; builtin_optab = log_optab; break;
- case BUILT_IN_TAN:
- case BUILT_IN_TANF:
- case BUILT_IN_TANL:
+ CASE_FLT_FN (BUILT_IN_LOG10):
+ errno_set = true; builtin_optab = log10_optab; break;
+ CASE_FLT_FN (BUILT_IN_LOG2):
+ errno_set = true; builtin_optab = log2_optab; break;
+ CASE_FLT_FN (BUILT_IN_LOG1P):
+ errno_set = true; builtin_optab = log1p_optab; break;
+ CASE_FLT_FN (BUILT_IN_ASIN):
+ builtin_optab = asin_optab; break;
+ CASE_FLT_FN (BUILT_IN_ACOS):
+ builtin_optab = acos_optab; break;
+ CASE_FLT_FN (BUILT_IN_TAN):
builtin_optab = tan_optab; break;
- case BUILT_IN_ATAN:
- case BUILT_IN_ATANF:
- case BUILT_IN_ATANL:
+ CASE_FLT_FN (BUILT_IN_ATAN):
builtin_optab = atan_optab; break;
- case BUILT_IN_FLOOR:
- case BUILT_IN_FLOORF:
- case BUILT_IN_FLOORL:
+ CASE_FLT_FN (BUILT_IN_FLOOR):
builtin_optab = floor_optab; break;
- case BUILT_IN_CEIL:
- case BUILT_IN_CEILF:
- case BUILT_IN_CEILL:
+ CASE_FLT_FN (BUILT_IN_CEIL):
builtin_optab = ceil_optab; break;
- case BUILT_IN_TRUNC:
- case BUILT_IN_TRUNCF:
- case BUILT_IN_TRUNCL:
+ CASE_FLT_FN (BUILT_IN_TRUNC):
builtin_optab = btrunc_optab; break;
- case BUILT_IN_ROUND:
- case BUILT_IN_ROUNDF:
- case BUILT_IN_ROUNDL:
+ CASE_FLT_FN (BUILT_IN_ROUND):
builtin_optab = round_optab; break;
- case BUILT_IN_NEARBYINT:
- case BUILT_IN_NEARBYINTF:
- case BUILT_IN_NEARBYINTL:
+ CASE_FLT_FN (BUILT_IN_NEARBYINT):
builtin_optab = nearbyint_optab; break;
+ CASE_FLT_FN (BUILT_IN_RINT):
+ builtin_optab = rint_optab; break;
+ CASE_FLT_FN (BUILT_IN_LRINT):
+ CASE_FLT_FN (BUILT_IN_LLRINT):
+ builtin_optab = lrint_optab; break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Make a suitable register to place result in. */
@@ -1705,7 +1856,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
/* Wrap the computation of the argument in a SAVE_EXPR, as we may
need to expand the argument again. This way, we will not perform
side-effects more the once. */
- narg = save_expr (arg);
+ narg = builtin_save_expr (arg);
if (narg != arg)
{
arg = narg;
@@ -1715,7 +1866,6 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
- emit_queue ();
start_sequence ();
/* Compute into TARGET.
@@ -1769,7 +1919,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
/* Check operand is a register with expected mode. */
if (operand
- && GET_CODE (operand) == REG
+ && REG_P (operand)
&& GET_MODE (operand) == mode)
{
/* Replace the REG_EQUAL note with a SQRT rtx. */
@@ -1798,6 +1948,7 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
{
optab builtin_optab;
rtx op0, op1, insns;
+ int op1_type = REAL_TYPE;
tree fndecl = get_callee_fndecl (exp);
tree arglist = TREE_OPERAND (exp, 1);
tree arg0, arg1, temp, narg;
@@ -1805,7 +1956,12 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
bool errno_set = true;
bool stable = true;
- if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+ if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP)
+ || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF)
+ || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
+ op1_type = INTEGER_TYPE;
+
+ if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE))
return 0;
arg0 = TREE_VALUE (arglist);
@@ -1813,16 +1969,18 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
switch (DECL_FUNCTION_CODE (fndecl))
{
- case BUILT_IN_POW:
- case BUILT_IN_POWF:
- case BUILT_IN_POWL:
+ CASE_FLT_FN (BUILT_IN_POW):
builtin_optab = pow_optab; break;
- case BUILT_IN_ATAN2:
- case BUILT_IN_ATAN2F:
- case BUILT_IN_ATAN2L:
+ CASE_FLT_FN (BUILT_IN_ATAN2):
builtin_optab = atan2_optab; break;
+ CASE_FLT_FN (BUILT_IN_LDEXP):
+ builtin_optab = ldexp_optab; break;
+ CASE_FLT_FN (BUILT_IN_FMOD):
+ builtin_optab = fmod_optab; break;
+ CASE_FLT_FN (BUILT_IN_DREM):
+ builtin_optab = drem_optab; break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Make a suitable register to place result in. */
@@ -1837,8 +1995,8 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
if (! flag_errno_math || ! HONOR_NANS (mode))
errno_set = false;
- /* Alway stabilize the argument list. */
- narg = save_expr (arg1);
+ /* Always stabilize the argument list. */
+ narg = builtin_save_expr (arg1);
if (narg != arg1)
{
arg1 = narg;
@@ -1848,7 +2006,7 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
else
temp = TREE_CHAIN (arglist);
- narg = save_expr (arg0);
+ narg = builtin_save_expr (arg0);
if (narg != arg0)
{
arg0 = narg;
@@ -1861,10 +2019,9 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
if (! stable)
exp = build_function_call_expr (fndecl, arglist);
- op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
- op1 = expand_expr (arg1, 0, VOIDmode, 0);
+ op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
+ op1 = expand_normal (arg1);
- emit_queue ();
start_sequence ();
/* Compute into TARGET.
@@ -1892,6 +2049,266 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
return target;
}
+/* Expand a call to the builtin sin and cos math functions.
+ Return 0 if a normal call should be emitted rather than expanding the
+ function in-line. EXP is the expression that is a call to the builtin
+ function; if convenient, the result should be placed in TARGET.
+ SUBTARGET may be used as the target for computing one of EXP's
+ operands. */
+
+static rtx
+expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
+{
+ optab builtin_optab;
+ rtx op0, insns;
+ tree fndecl = get_callee_fndecl (exp);
+ tree arglist = TREE_OPERAND (exp, 1);
+ enum machine_mode mode;
+ tree arg, narg;
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return 0;
+
+ arg = TREE_VALUE (arglist);
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_SIN):
+ CASE_FLT_FN (BUILT_IN_COS):
+ builtin_optab = sincos_optab; break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Make a suitable register to place result in. */
+ mode = TYPE_MODE (TREE_TYPE (exp));
+
+ /* Check if sincos insn is available, otherwise fallback
+ to sin or cos insn. */
+ if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_SIN):
+ builtin_optab = sin_optab; break;
+ CASE_FLT_FN (BUILT_IN_COS):
+ builtin_optab = cos_optab; break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ /* Before working hard, check whether the instruction is available. */
+ if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ {
+ target = gen_reg_rtx (mode);
+
+ /* Wrap the computation of the argument in a SAVE_EXPR, as we may
+ need to expand the argument again. This way, we will not perform
+ side-effects more the once. */
+ narg = save_expr (arg);
+ if (narg != arg)
+ {
+ arg = narg;
+ arglist = build_tree_list (NULL_TREE, arg);
+ exp = build_function_call_expr (fndecl, arglist);
+ }
+
+ op0 = expand_expr (arg, subtarget, VOIDmode, 0);
+
+ start_sequence ();
+
+ /* Compute into TARGET.
+ Set TARGET to wherever the result comes back. */
+ if (builtin_optab == sincos_optab)
+ {
+ int result;
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_SIN):
+ result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
+ break;
+ CASE_FLT_FN (BUILT_IN_COS):
+ result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ gcc_assert (result);
+ }
+ else
+ {
+ target = expand_unop (mode, builtin_optab, op0, target, 0);
+ }
+
+ if (target != 0)
+ {
+ /* Output the entire sequence. */
+ insns = get_insns ();
+ end_sequence ();
+ emit_insn (insns);
+ return target;
+ }
+
+ /* If we were unable to expand via the builtin, stop the sequence
+ (without outputting the insns) and call to the library function
+ with the stabilized argument list. */
+ end_sequence ();
+ }
+
+ target = expand_call (exp, target, target == const0_rtx);
+
+ return target;
+}
+
+/* Expand a call to the builtin sincos math function.
+ Return 0 if a normal call should be emitted rather than expanding the
+ function in-line. EXP is the expression that is a call to the builtin
+ function. */
+
+static rtx
+expand_builtin_sincos (tree exp)
+{
+ rtx op0, op1, op2, target1, target2;
+ tree arglist = TREE_OPERAND (exp, 1);
+ enum machine_mode mode;
+ tree arg, sinp, cosp;
+ int result;
+
+ if (!validate_arglist (arglist, REAL_TYPE,
+ POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+
+ arg = TREE_VALUE (arglist);
+ sinp = TREE_VALUE (TREE_CHAIN (arglist));
+ cosp = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+
+ /* Make a suitable register to place result in. */
+ mode = TYPE_MODE (TREE_TYPE (arg));
+
+ /* Check if sincos insn is available, otherwise emit the call. */
+ if (sincos_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
+ return NULL_RTX;
+
+ target1 = gen_reg_rtx (mode);
+ target2 = gen_reg_rtx (mode);
+
+ op0 = expand_normal (arg);
+ op1 = expand_normal (build_fold_indirect_ref (sinp));
+ op2 = expand_normal (build_fold_indirect_ref (cosp));
+
+ /* Compute into target1 and target2.
+ Set TARGET to wherever the result comes back. */
+ result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
+ gcc_assert (result);
+
+ /* Move target1 and target2 to the memory locations indicated
+ by op1 and op2. */
+ emit_move_insn (op1, target1);
+ emit_move_insn (op2, target2);
+
+ return const0_rtx;
+}
+
+/* Expand a call to one of the builtin rounding functions (lfloor).
+ If expanding via optab fails, lower expression to (int)(floor(x)).
+ EXP is the expression that is a call to the builtin function;
+ if convenient, the result should be placed in TARGET. SUBTARGET may
+ be used as the target for computing one of EXP's operands. */
+
+static rtx
+expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
+{
+ optab builtin_optab;
+ rtx op0, insns, tmp;
+ tree fndecl = get_callee_fndecl (exp);
+ tree arglist = TREE_OPERAND (exp, 1);
+ enum built_in_function fallback_fn;
+ tree fallback_fndecl;
+ enum machine_mode mode;
+ tree arg, narg;
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ gcc_unreachable ();
+
+ arg = TREE_VALUE (arglist);
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_LCEIL):
+ CASE_FLT_FN (BUILT_IN_LLCEIL):
+ builtin_optab = lceil_optab;
+ fallback_fn = BUILT_IN_CEIL;
+ break;
+
+ CASE_FLT_FN (BUILT_IN_LFLOOR):
+ CASE_FLT_FN (BUILT_IN_LLFLOOR):
+ builtin_optab = lfloor_optab;
+ fallback_fn = BUILT_IN_FLOOR;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Make a suitable register to place result in. */
+ mode = TYPE_MODE (TREE_TYPE (exp));
+
+ /* Before working hard, check whether the instruction is available. */
+ if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ {
+ target = gen_reg_rtx (mode);
+
+ /* Wrap the computation of the argument in a SAVE_EXPR, as we may
+ need to expand the argument again. This way, we will not perform
+ side-effects more the once. */
+ narg = builtin_save_expr (arg);
+ if (narg != arg)
+ {
+ arg = narg;
+ arglist = build_tree_list (NULL_TREE, arg);
+ exp = build_function_call_expr (fndecl, arglist);
+ }
+
+ op0 = expand_expr (arg, subtarget, VOIDmode, 0);
+
+ start_sequence ();
+
+ /* Compute into TARGET.
+ Set TARGET to wherever the result comes back. */
+ target = expand_unop (mode, builtin_optab, op0, target, 0);
+
+ if (target != 0)
+ {
+ /* Output the entire sequence. */
+ insns = get_insns ();
+ end_sequence ();
+ emit_insn (insns);
+ return target;
+ }
+
+ /* If we were unable to expand via the builtin, stop the sequence
+ (without outputting the insns). */
+ end_sequence ();
+ }
+
+ /* Fall back to floating point rounding optab. */
+ fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
+ /* We shouldn't get here on targets without TARGET_C99_FUNCTIONS.
+ ??? Perhaps convert (int)floorf(x) into (int)floor((double)x). */
+ gcc_assert (fallback_fndecl != NULL_TREE);
+ exp = build_function_call_expr (fallback_fndecl, arglist);
+
+ tmp = expand_normal (exp);
+
+ /* Truncate the result of floating point optab to integer
+ via expand_fix (). */
+ target = gen_reg_rtx (mode);
+ expand_fix (target, tmp, 0);
+
+ return target;
+}
+
/* To evaluate powi(x,n), the floating point value x raised to the
constant integer exponent n, we use a hybrid algorithm that
combines the "window method" with look-up tables. For an
@@ -1905,7 +2322,7 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
multiplications to inline before calling the system library's pow
function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
so this default never requires calling pow, powf or powl. */
-
+
#ifndef POWI_MAX_MULTS
#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
#endif
@@ -2022,7 +2439,7 @@ powi_cost (HOST_WIDE_INT n)
result++;
}
}
-
+
return result + powi_lookup_cost (val, cache);
}
@@ -2040,7 +2457,7 @@ expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
if (n < POWI_TABLE_SIZE)
{
if (cache[n])
- return cache[n];
+ return cache[n];
target = gen_reg_rtx (mode);
cache[n] = target;
@@ -2071,7 +2488,7 @@ expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
floating point operand in mode MODE, and N is the exponent. This
function needs to be kept in sync with powi_cost above. */
-
+
static rtx
expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
{
@@ -2141,7 +2558,74 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget)
}
}
}
- return expand_builtin_mathfn_2 (exp, target, NULL_RTX);
+
+ if (! flag_unsafe_math_optimizations)
+ return NULL_RTX;
+ return expand_builtin_mathfn_2 (exp, target, subtarget);
+}
+
+/* Expand a call to the powi built-in mathematical function. Return 0 if
+ a normal call should be emitted rather than expanding the function
+ in-line. EXP is the expression that is a call to the builtin
+ function; if convenient, the result should be placed in TARGET. */
+
+static rtx
+expand_builtin_powi (tree exp, rtx target, rtx subtarget)
+{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg0, arg1;
+ rtx op0, op1;
+ enum machine_mode mode;
+ enum machine_mode mode2;
+
+ if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ mode = TYPE_MODE (TREE_TYPE (exp));
+
+ /* Handle constant power. */
+
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg1))
+ {
+ HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
+
+ /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
+ Otherwise, check the number of multiplications required. */
+ if ((TREE_INT_CST_HIGH (arg1) == 0
+ || TREE_INT_CST_HIGH (arg1) == -1)
+ && ((n >= -1 && n <= 2)
+ || (! optimize_size
+ && powi_cost (n) <= POWI_MAX_MULTS)))
+ {
+ op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
+ op0 = force_reg (mode, op0);
+ return expand_powi (op0, mode, n);
+ }
+ }
+
+ /* Emit a libcall to libgcc. */
+
+ /* Mode of the 2nd argument must match that of an int. */
+ mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
+
+ if (target == NULL_RTX)
+ target = gen_reg_rtx (mode);
+
+ op0 = expand_expr (arg0, subtarget, mode, 0);
+ if (GET_MODE (op0) != mode)
+ op0 = convert_to_mode (mode, op0, 0);
+ op1 = expand_expr (arg1, 0, mode2, 0);
+ if (GET_MODE (op1) != mode2)
+ op1 = convert_to_mode (mode2, op1, 0);
+
+ target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc,
+ target, LCT_CONST_MAKE_BLOCK, mode, 2,
+ op0, mode, op1, mode2);
+
+ return target;
}
/* Expand expression EXP which is a call to the strlen builtin. Return 0
@@ -2201,7 +2685,7 @@ expand_builtin_strlen (tree arglist, rtx target,
/* Make a place to write the result of the instruction. */
result = target;
if (! (result != 0
- && GET_CODE (result) == REG
+ && REG_P (result)
&& GET_MODE (result) == insn_mode
&& REGNO (result) >= FIRST_PSEUDO_REGISTER))
result = gen_reg_rtx (insn_mode);
@@ -2229,8 +2713,7 @@ expand_builtin_strlen (tree arglist, rtx target,
/* Now that we are assured of success, expand the source. */
start_sequence ();
- pat = memory_address (BLKmode,
- expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
+ pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
if (pat != src_reg)
emit_move_insn (src_reg, pat);
pat = get_insns ();
@@ -2258,53 +2741,15 @@ expand_builtin_strlen (tree arglist, rtx target,
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
-expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
- return 0;
- else
+ if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
- tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
- tree fn;
- const char *p1, *p2;
-
- p2 = c_getstr (s2);
- if (p2 == NULL)
- return 0;
-
- p1 = c_getstr (s1);
- if (p1 != NULL)
- {
- const char *r = strstr (p1, p2);
-
- if (r == NULL)
- return const0_rtx;
-
- /* Return an offset into the constant string argument. */
- return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
- s1, convert (TREE_TYPE (s1),
- ssize_int (r - p1)))),
- target, mode, EXPAND_NORMAL);
- }
-
- if (p2[0] == '\0')
- return expand_expr (s1, target, mode, EXPAND_NORMAL);
-
- if (p2[1] != '\0')
- return 0;
-
- fn = implicit_built_in_decls[BUILT_IN_STRCHR];
- if (!fn)
- return 0;
-
- /* New argument list transforming strstr(s1, s2) to
- strchr(s1, s2[0]). */
- arglist =
- build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
- arglist = tree_cons (NULL_TREE, s1, arglist);
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ tree result = fold_builtin_strstr (arglist, type);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
+ return 0;
}
/* Expand a call to the strchr builtin. Return 0 if we failed the
@@ -2312,43 +2757,17 @@ expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode)
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
-expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
- return 0;
- else
+ if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
- tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
- const char *p1;
-
- if (TREE_CODE (s2) != INTEGER_CST)
- return 0;
-
- p1 = c_getstr (s1);
- if (p1 != NULL)
- {
- char c;
- const char *r;
-
- if (target_char_cast (s2, &c))
- return 0;
-
- r = strchr (p1, c);
-
- if (r == NULL)
- return const0_rtx;
-
- /* Return an offset into the constant string argument. */
- return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
- s1, convert (TREE_TYPE (s1),
- ssize_int (r - p1)))),
- target, mode, EXPAND_NORMAL);
- }
+ tree result = fold_builtin_strchr (arglist, type);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
- /* FIXME: Should use here strchrM optab so that ports can optimize
- this. */
- return 0;
+ /* FIXME: Should use strchrM optab so that ports can optimize this. */
}
+ return 0;
}
/* Expand a call to the strrchr builtin. Return 0 if we failed the
@@ -2356,51 +2775,15 @@ expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode)
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
-expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
- return 0;
- else
+ if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
- tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
- tree fn;
- const char *p1;
-
- if (TREE_CODE (s2) != INTEGER_CST)
- return 0;
-
- p1 = c_getstr (s1);
- if (p1 != NULL)
- {
- char c;
- const char *r;
-
- if (target_char_cast (s2, &c))
- return 0;
-
- r = strrchr (p1, c);
-
- if (r == NULL)
- return const0_rtx;
-
- /* Return an offset into the constant string argument. */
- return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
- s1, convert (TREE_TYPE (s1),
- ssize_int (r - p1)))),
- target, mode, EXPAND_NORMAL);
- }
-
- if (! integer_zerop (s2))
- return 0;
-
- fn = implicit_built_in_decls[BUILT_IN_STRCHR];
- if (!fn)
- return 0;
-
- /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ tree result = fold_builtin_strrchr (arglist, type);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
+ return 0;
}
/* Expand a call to the strpbrk builtin. Return 0 if we failed the
@@ -2408,59 +2791,15 @@ expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode)
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
-expand_builtin_strpbrk (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
- return 0;
- else
+ if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
- tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
- tree fn;
- const char *p1, *p2;
-
- p2 = c_getstr (s2);
- if (p2 == NULL)
- return 0;
-
- p1 = c_getstr (s1);
- if (p1 != NULL)
- {
- const char *r = strpbrk (p1, p2);
-
- if (r == NULL)
- return const0_rtx;
-
- /* Return an offset into the constant string argument. */
- return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
- s1, convert (TREE_TYPE (s1),
- ssize_int (r - p1)))),
- target, mode, EXPAND_NORMAL);
- }
-
- if (p2[0] == '\0')
- {
- /* strpbrk(x, "") == NULL.
- Evaluate and ignore the arguments in case they had
- side-effects. */
- expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
-
- if (p2[1] != '\0')
- return 0; /* Really call strpbrk. */
-
- fn = implicit_built_in_decls[BUILT_IN_STRCHR];
- if (!fn)
- return 0;
-
- /* New argument list transforming strpbrk(s1, s2) to
- strchr(s1, s2[0]). */
- arglist =
- build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
- arglist = tree_cons (NULL_TREE, s1, arglist);
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ tree result = fold_builtin_strpbrk (arglist, type);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
+ return 0;
}
/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
@@ -2473,10 +2812,9 @@ builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
{
const char *str = (const char *) data;
- if (offset < 0
- || ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
- > strlen (str) + 1))
- abort (); /* Attempt to read past the end of constant string. */
+ gcc_assert (offset >= 0
+ && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
+ <= strlen (str) + 1));
return c_readstr (str + offset, mode);
}
@@ -2486,8 +2824,10 @@ builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). */
static rtx
-expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
{
+ tree fndecl = get_callee_fndecl (exp);
+ tree arglist = TREE_OPERAND (exp, 1);
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
@@ -2501,35 +2841,32 @@ expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, dest_addr, len_rtx;
+ tree result = fold_builtin_memory_op (arglist, TREE_TYPE (TREE_TYPE (fndecl)),
+ false, /*endp=*/0);
- /* If DEST is not a pointer type, call the normal function. */
- if (dest_align == 0)
- return 0;
-
- /* If the LEN parameter is zero, return DEST. */
- if (integer_zerop (len))
+ if (result)
{
- /* Evaluate and ignore SRC in case it has side-effects. */
- expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
+ while (TREE_CODE (result) == COMPOUND_EXPR)
+ {
+ expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
+ EXPAND_NORMAL);
+ result = TREE_OPERAND (result, 1);
+ }
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
- /* If SRC and DEST are the same (and not volatile), return DEST. */
- if (operand_equal_p (src, dest, 0))
- {
- /* Evaluate and ignore LEN in case it has side-effects. */
- expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
- }
+ /* If DEST is not a pointer type, call the normal function. */
+ if (dest_align == 0)
+ return 0;
/* If either SRC is not a pointer type, don't do this
- operation in-line. */
+ operation in-line. */
if (src_align == 0)
return 0;
- dest_mem = get_memory_rtx (dest);
+ dest_mem = get_memory_rtx (dest, len);
set_mem_align (dest_mem, dest_align);
- len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+ len_rtx = expand_normal (len);
src_str = c_getstr (src);
/* If SRC is a string constant and block move would be done
@@ -2549,12 +2886,13 @@ expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
return dest_mem;
}
- src_mem = get_memory_rtx (src);
+ src_mem = get_memory_rtx (src, len);
set_mem_align (src_mem, src_align);
/* Copy word part most expediently. */
dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
- BLOCK_OP_NORMAL);
+ CALL_EXPR_TAILCALL (exp)
+ ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
if (dest_addr == 0)
{
@@ -2566,7 +2904,7 @@ expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
}
/* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
- Return 0 if we failed the caller should emit a normal call,
+ Return 0 if we failed; the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). If ENDP is 0 return the
destination pointer, if ENDP is 1 return the end pointer ala
@@ -2574,7 +2912,7 @@ expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
stpcpy. */
static rtx
-expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
+expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
int endp)
{
if (!validate_arglist (arglist,
@@ -2601,49 +2939,29 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, len_rtx;
+ tree result = fold_builtin_memory_op (arglist, type, false, endp);
- /* If DEST is not a pointer type, call the normal function. */
- if (dest_align == 0)
- return 0;
-
- /* If SRC and DEST are the same (and not volatile), do nothing. */
- if (operand_equal_p (src, dest, 0))
+ if (result)
{
- tree expr;
-
- if (endp == 0)
+ while (TREE_CODE (result) == COMPOUND_EXPR)
{
- /* Evaluate and ignore LEN in case it has side-effects. */
- expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
+ expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
+ EXPAND_NORMAL);
+ result = TREE_OPERAND (result, 1);
}
-
- if (endp == 2)
- len = fold (build (MINUS_EXPR, TREE_TYPE (len), dest,
- integer_one_node));
- len = convert (TREE_TYPE (dest), len);
- expr = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, len));
- return expand_expr (expr, target, mode, EXPAND_NORMAL);
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
- /* If LEN is not constant, call the normal function. */
- if (! host_integerp (len, 1))
+ /* If either SRC or DEST is not a pointer type, don't do this
+ operation in-line. */
+ if (dest_align == 0 || src_align == 0)
return 0;
-
- /* If the LEN parameter is zero, return DEST. */
- if (tree_low_cst (len, 1) == 0)
- {
- /* Evaluate and ignore SRC in case it has side-effects. */
- expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
- }
- /* If either SRC is not a pointer type, don't do this
- operation in-line. */
- if (src_align == 0)
+ /* If LEN is not constant, call the normal function. */
+ if (! host_integerp (len, 1))
return 0;
- len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+ len_rtx = expand_normal (len);
src_str = c_getstr (src);
/* If SRC is a string constant and block move would be done
@@ -2655,7 +2973,7 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
&& can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
(void *) src_str, dest_align))
{
- dest_mem = get_memory_rtx (dest);
+ dest_mem = get_memory_rtx (dest, len);
set_mem_align (dest_mem, dest_align);
dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
builtin_memcpy_read_str,
@@ -2669,9 +2987,9 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
&& can_move_by_pieces (INTVAL (len_rtx),
MIN (dest_align, src_align)))
{
- dest_mem = get_memory_rtx (dest);
+ dest_mem = get_memory_rtx (dest, len);
set_mem_align (dest_mem, dest_align);
- src_mem = get_memory_rtx (src);
+ src_mem = get_memory_rtx (src, len);
set_mem_align (src_mem, src_align);
dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
MIN (dest_align, src_align), endp);
@@ -2685,10 +3003,11 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
}
/* Expand expression EXP, which is a call to the memmove builtin. Return 0
- if we failed the caller should emit a normal call. */
+ if we failed; the caller should emit a normal call. */
static rtx
-expand_builtin_memmove (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_memmove (tree arglist, tree type, rtx target,
+ enum machine_mode mode, tree orig_exp)
{
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -2702,41 +3021,49 @@ expand_builtin_memmove (tree arglist, rtx target, enum machine_mode mode)
unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
+ tree result = fold_builtin_memory_op (arglist, type, false, /*endp=*/3);
- /* If DEST is not a pointer type, call the normal function. */
- if (dest_align == 0)
- return 0;
-
- /* If the LEN parameter is zero, return DEST. */
- if (integer_zerop (len))
+ if (result)
{
- /* Evaluate and ignore SRC in case it has side-effects. */
- expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
+ while (TREE_CODE (result) == COMPOUND_EXPR)
+ {
+ expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
+ EXPAND_NORMAL);
+ result = TREE_OPERAND (result, 1);
+ }
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
- /* If SRC and DEST are the same (and not volatile), return DEST. */
- if (operand_equal_p (src, dest, 0))
- {
- /* Evaluate and ignore LEN in case it has side-effects. */
- expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
- }
+ /* If DEST is not a pointer type, call the normal function. */
+ if (dest_align == 0)
+ return 0;
/* If either SRC is not a pointer type, don't do this
- operation in-line. */
+ operation in-line. */
if (src_align == 0)
return 0;
/* If src is categorized for a readonly section we can use
normal memcpy. */
if (readonly_data_expr (src))
- {
- tree const fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ {
+ tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ fn = build_function_call_expr (fn, arglist);
+ if (TREE_CODE (fn) == CALL_EXPR)
+ CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
+ return expand_expr (fn, target, mode, EXPAND_NORMAL);
+ }
+
+ /* If length is 1 and we can expand memcpy call inline,
+ it is ok to use memcpy as well. */
+ if (integer_onep (len))
+ {
+ rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
+ /*endp=*/0);
+ if (ret)
+ return ret;
}
/* Otherwise, call the normal function. */
@@ -2748,8 +3075,10 @@ expand_builtin_memmove (tree arglist, rtx target, enum machine_mode mode)
if we failed the caller should emit a normal call. */
static rtx
-expand_builtin_bcopy (tree arglist)
+expand_builtin_bcopy (tree exp)
{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree type = TREE_TYPE (exp);
tree src, dest, size, newarglist;
if (!validate_arglist (arglist,
@@ -2765,47 +3094,107 @@ expand_builtin_bcopy (tree arglist)
so that if it isn't expanded inline, we fallback to
calling bcopy instead of memmove. */
- newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
+ newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
newarglist = tree_cons (NULL_TREE, src, newarglist);
newarglist = tree_cons (NULL_TREE, dest, newarglist);
- return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
+ return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp);
}
-/* Expand expression EXP, which is a call to the strcpy builtin. Return 0
- if we failed the caller should emit a normal call, otherwise try to get
- the result in TARGET, if convenient (and in mode MODE if that's
- convenient). */
+#ifndef HAVE_movstr
+# define HAVE_movstr 0
+# define CODE_FOR_movstr CODE_FOR_nothing
+#endif
+
+/* Expand into a movstr instruction, if one is available. Return 0 if
+ we failed, the caller should emit a normal call, otherwise try to
+ get the result in TARGET, if convenient. If ENDP is 0 return the
+ destination pointer, if ENDP is 1 return the end pointer ala
+ mempcpy, and if ENDP is 2 return the end pointer minus one ala
+ stpcpy. */
static rtx
-expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
+expand_movstr (tree dest, tree src, rtx target, int endp)
{
- tree fn, len, src, dst;
+ rtx end;
+ rtx dest_mem;
+ rtx src_mem;
+ rtx insn;
+ const struct insn_data * data;
- if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ if (!HAVE_movstr)
return 0;
- src = TREE_VALUE (TREE_CHAIN (arglist));
- dst = TREE_VALUE (arglist);
+ dest_mem = get_memory_rtx (dest, NULL);
+ src_mem = get_memory_rtx (src, NULL);
+ if (!endp)
+ {
+ target = force_reg (Pmode, XEXP (dest_mem, 0));
+ dest_mem = replace_equiv_address (dest_mem, target);
+ end = gen_reg_rtx (Pmode);
+ }
+ else
+ {
+ if (target == 0 || target == const0_rtx)
+ {
+ end = gen_reg_rtx (Pmode);
+ if (target == 0)
+ target = end;
+ }
+ else
+ end = target;
+ }
- /* If SRC and DST are equal (and not volatile), return DST. */
- if (operand_equal_p (src, dst, 0))
- return expand_expr (dst, target, mode, EXPAND_NORMAL);
+ data = insn_data + CODE_FOR_movstr;
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
- if (!fn)
- return 0;
+ if (data->operand[0].mode != VOIDmode)
+ end = gen_lowpart (data->operand[0].mode, end);
- len = c_strlen (src, 1);
- if (len == 0 || TREE_SIDE_EFFECTS (len))
- return 0;
+ insn = data->genfun (end, dest_mem, src_mem);
- len = size_binop (PLUS_EXPR, len, ssize_int (1));
- arglist = build_tree_list (NULL_TREE, len);
- arglist = tree_cons (NULL_TREE, src, arglist);
- arglist = tree_cons (NULL_TREE, dst, arglist);
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ gcc_assert (insn);
+
+ emit_insn (insn);
+
+ /* movstr is supposed to set end to the address of the NUL
+ terminator. If the caller requested a mempcpy-like return value,
+ adjust it. */
+ if (endp == 1 && target != const0_rtx)
+ {
+ rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
+ emit_move_insn (target, force_operand (tem, NULL_RTX));
+ }
+
+ return target;
+}
+
+/* Expand expression EXP, which is a call to the strcpy builtin. Return 0
+ if we failed the caller should emit a normal call, otherwise try to get
+ the result in TARGET, if convenient (and in mode MODE if that's
+ convenient). */
+
+static rtx
+expand_builtin_strcpy (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
+{
+ if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ {
+ tree result = fold_builtin_strcpy (fndecl, arglist, 0);
+ if (result)
+ {
+ while (TREE_CODE (result) == COMPOUND_EXPR)
+ {
+ expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
+ EXPAND_NORMAL);
+ result = TREE_OPERAND (result, 1);
+ }
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
+ }
+
+ return expand_movstr (TREE_VALUE (arglist),
+ TREE_VALUE (TREE_CHAIN (arglist)),
+ target, /*endp=*/0);
+ }
+ return 0;
}
/* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
@@ -2814,39 +3203,82 @@ expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
mode MODE if that's convenient). */
static rtx
-expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
{
+ tree arglist = TREE_OPERAND (exp, 1);
+ /* If return value is ignored, transform stpcpy into strcpy. */
+ if (target == const0_rtx)
+ {
+ tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ if (!fn)
+ return 0;
+
+ return expand_expr (build_function_call_expr (fn, arglist),
+ target, mode, EXPAND_NORMAL);
+ }
+
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
- tree dst, src, len;
-
- /* If return value is ignored, transform stpcpy into strcpy. */
- if (target == const0_rtx)
- {
- tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
- if (!fn)
- return 0;
-
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
- }
+ tree dst, src, len, lenp1;
+ tree narglist;
+ rtx ret;
/* Ensure we get an actual string whose length can be evaluated at
- compile-time, not an expression containing a string. This is
- because the latter will potentially produce pessimized code
- when used to produce the return value. */
+ compile-time, not an expression containing a string. This is
+ because the latter will potentially produce pessimized code
+ when used to produce the return value. */
src = TREE_VALUE (TREE_CHAIN (arglist));
if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
- return 0;
+ return expand_movstr (TREE_VALUE (arglist),
+ TREE_VALUE (TREE_CHAIN (arglist)),
+ target, /*endp=*/2);
dst = TREE_VALUE (arglist);
- len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
- arglist = build_tree_list (NULL_TREE, len);
- arglist = tree_cons (NULL_TREE, src, arglist);
- arglist = tree_cons (NULL_TREE, dst, arglist);
- return expand_builtin_mempcpy (arglist, target, mode, /*endp=*/2);
+ lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
+ narglist = build_tree_list (NULL_TREE, lenp1);
+ narglist = tree_cons (NULL_TREE, src, narglist);
+ narglist = tree_cons (NULL_TREE, dst, narglist);
+ ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
+ target, mode, /*endp=*/2);
+
+ if (ret)
+ return ret;
+
+ if (TREE_CODE (len) == INTEGER_CST)
+ {
+ rtx len_rtx = expand_normal (len);
+
+ if (GET_CODE (len_rtx) == CONST_INT)
+ {
+ ret = expand_builtin_strcpy (get_callee_fndecl (exp),
+ arglist, target, mode);
+
+ if (ret)
+ {
+ if (! target)
+ {
+ if (mode != VOIDmode)
+ target = gen_reg_rtx (mode);
+ else
+ target = gen_reg_rtx (GET_MODE (ret));
+ }
+ if (GET_MODE (target) != GET_MODE (ret))
+ ret = gen_lowpart (GET_MODE (target), ret);
+
+ ret = plus_constant (ret, INTVAL (len_rtx));
+ ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
+ gcc_assert (ret);
+
+ return target;
+ }
+ }
+ }
+
+ return expand_movstr (TREE_VALUE (arglist),
+ TREE_VALUE (TREE_CHAIN (arglist)),
+ target, /*endp=*/2);
}
}
@@ -2870,41 +3302,36 @@ builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
if we failed the caller should emit a normal call. */
static rtx
-expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist,
- POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
- return 0;
- else
+ tree fndecl = get_callee_fndecl (exp);
+ tree arglist = TREE_OPERAND (exp, 1);
+ if (validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- tree fn;
+ tree result = fold_builtin_strncpy (fndecl, arglist, slen);
- /* We must be passed a constant len parameter. */
- if (TREE_CODE (len) != INTEGER_CST)
- return 0;
-
- /* If the len parameter is zero, return the dst parameter. */
- if (integer_zerop (len))
+ if (result)
{
- /* Evaluate and ignore the src argument in case it has
- side-effects. */
- expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
- VOIDmode, EXPAND_NORMAL);
- /* Return the dst parameter. */
- return expand_expr (TREE_VALUE (arglist), target, mode,
- EXPAND_NORMAL);
+ while (TREE_CODE (result) == COMPOUND_EXPR)
+ {
+ expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
+ EXPAND_NORMAL);
+ result = TREE_OPERAND (result, 1);
+ }
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
- /* Now, we must be passed a constant src ptr parameter. */
- if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
+ /* We must be passed a constant len and src parameter. */
+ if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
return 0;
slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
/* We're required to pad with trailing zeros if the requested
- len is greater than strlen(s2)+1. In that case try to
+ len is greater than strlen(s2)+1. In that case try to
use store_by_pieces, if it fails, punt. */
if (tree_int_cst_lt (slen, len))
{
@@ -2920,7 +3347,7 @@ expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
(void *) p, dest_align))
return 0;
- dest_mem = get_memory_rtx (dest);
+ dest_mem = get_memory_rtx (dest, len);
store_by_pieces (dest_mem, tree_low_cst (len, 1),
builtin_strncpy_read_str,
(void *) p, dest_align, 0);
@@ -2928,14 +3355,8 @@ expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
}
-
- /* OK transform into builtin memcpy. */
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
- if (!fn)
- return 0;
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
}
+ return 0;
}
/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
@@ -2986,7 +3407,8 @@ builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
convenient). */
static rtx
-expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
+ tree orig_exp)
{
if (!validate_arglist (arglist,
POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -2996,12 +3418,14 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
tree dest = TREE_VALUE (arglist);
tree val = TREE_VALUE (TREE_CHAIN (arglist));
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ tree fndecl, fn;
+ enum built_in_function fcode;
char c;
-
- unsigned int dest_align
- = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
+ unsigned int dest_align;
rtx dest_mem, dest_addr, len_rtx;
+ dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
+
/* If DEST is not a pointer type, don't do this
operation in-line. */
if (dest_align == 0)
@@ -3015,64 +3439,69 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
return expand_expr (dest, target, mode, EXPAND_NORMAL);
}
+ /* Stabilize the arguments in case we fail. */
+ dest = builtin_save_expr (dest);
+ val = builtin_save_expr (val);
+ len = builtin_save_expr (len);
+
+ len_rtx = expand_normal (len);
+ dest_mem = get_memory_rtx (dest, len);
+
if (TREE_CODE (val) != INTEGER_CST)
{
rtx val_rtx;
- if (!host_integerp (len, 1))
- return 0;
-
- if (optimize_size && tree_low_cst (len, 1) > 1)
- return 0;
+ val_rtx = expand_normal (val);
+ val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
+ val_rtx, 0);
/* Assume that we can memset by pieces if we can store the
* the coefficients by pieces (in the required modes).
* We can't pass builtin_memset_gen_str as that emits RTL. */
c = 1;
- if (!can_store_by_pieces (tree_low_cst (len, 1),
- builtin_memset_read_str,
- &c, dest_align))
- return 0;
+ if (host_integerp (len, 1)
+ && !(optimize_size && tree_low_cst (len, 1) > 1)
+ && can_store_by_pieces (tree_low_cst (len, 1),
+ builtin_memset_read_str, &c, dest_align))
+ {
+ val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
+ val_rtx);
+ store_by_pieces (dest_mem, tree_low_cst (len, 1),
+ builtin_memset_gen_str, val_rtx, dest_align, 0);
+ }
+ else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
+ dest_align))
+ goto do_libcall;
- val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
- val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
- val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
- val_rtx);
- dest_mem = get_memory_rtx (dest);
- store_by_pieces (dest_mem, tree_low_cst (len, 1),
- builtin_memset_gen_str,
- val_rtx, dest_align, 0);
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
}
if (target_char_cast (val, &c))
- return 0;
+ goto do_libcall;
if (c)
{
- if (!host_integerp (len, 1))
- return 0;
- if (!can_store_by_pieces (tree_low_cst (len, 1),
- builtin_memset_read_str, &c,
- dest_align))
- return 0;
+ if (host_integerp (len, 1)
+ && !(optimize_size && tree_low_cst (len, 1) > 1)
+ && can_store_by_pieces (tree_low_cst (len, 1),
+ builtin_memset_read_str, &c, dest_align))
+ store_by_pieces (dest_mem, tree_low_cst (len, 1),
+ builtin_memset_read_str, &c, dest_align, 0);
+ else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
+ dest_align))
+ goto do_libcall;
- dest_mem = get_memory_rtx (dest);
- store_by_pieces (dest_mem, tree_low_cst (len, 1),
- builtin_memset_read_str,
- &c, dest_align, 0);
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
}
- len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
-
- dest_mem = get_memory_rtx (dest);
set_mem_align (dest_mem, dest_align);
- dest_addr = clear_storage (dest_mem, len_rtx);
+ dest_addr = clear_storage (dest_mem, len_rtx,
+ CALL_EXPR_TAILCALL (orig_exp)
+ ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
if (dest_addr == 0)
{
@@ -3081,6 +3510,19 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
}
return dest_addr;
+
+ do_libcall:
+ fndecl = get_callee_fndecl (orig_exp);
+ fcode = DECL_FUNCTION_CODE (fndecl);
+ gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO);
+ arglist = build_tree_list (NULL_TREE, len);
+ if (fcode == BUILT_IN_MEMSET)
+ arglist = tree_cons (NULL_TREE, val, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+ fn = build_function_call_expr (fndecl, arglist);
+ if (TREE_CODE (fn) == CALL_EXPR)
+ CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
+ return expand_call (fn, target, target == const0_rtx);
}
}
@@ -3088,8 +3530,9 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
if we failed the caller should emit a normal call. */
static rtx
-expand_builtin_bzero (tree arglist)
+expand_builtin_bzero (tree exp)
{
+ tree arglist = TREE_OPERAND (exp, 1);
tree dest, size, newarglist;
if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -3103,11 +3546,11 @@ expand_builtin_bzero (tree arglist)
so that if it isn't expanded inline, we fallback to
calling bzero instead of memset. */
- newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
+ newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
newarglist = tree_cons (NULL_TREE, dest, newarglist);
- return expand_builtin_memset (newarglist, const0_rtx, VOIDmode);
+ return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp);
}
/* Expand expression EXP, which is a call to the memcmp built-in function.
@@ -3119,69 +3562,21 @@ static rtx
expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
enum machine_mode mode)
{
- tree arg1, arg2, len;
- const char *p1, *p2;
-
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
-
- arg1 = TREE_VALUE (arglist);
- arg2 = TREE_VALUE (TREE_CHAIN (arglist));
- len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-
- /* If the len parameter is zero, return zero. */
- if (integer_zerop (len))
- {
- /* Evaluate and ignore arg1 and arg2 in case they have
- side-effects. */
- expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
- expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
-
- /* If both arguments are equal (and not volatile), return zero. */
- if (operand_equal_p (arg1, arg2, 0))
- {
- /* Evaluate and ignore len in case it has side-effects. */
- expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
-
- p1 = c_getstr (arg1);
- p2 = c_getstr (arg2);
-
- /* If all arguments are constant, and the value of len is not greater
- than the lengths of arg1 and arg2, evaluate at compile-time. */
- if (host_integerp (len, 1) && p1 && p2
- && compare_tree_int (len, strlen (p1) + 1) <= 0
- && compare_tree_int (len, strlen (p2) + 1) <= 0)
+ else
{
- const int r = memcmp (p1, p2, tree_low_cst (len, 1));
-
- return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
+ tree result = fold_builtin_memcmp (arglist);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
- /* If len parameter is one, return an expression corresponding to
- (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
- if (integer_onep (len))
- {
- tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
- tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
- tree ind1 =
- fold (build1 (CONVERT_EXPR, integer_type_node,
- build1 (INDIRECT_REF, cst_uchar_node,
- build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
- tree ind2 =
- fold (build1 (CONVERT_EXPR, integer_type_node,
- build1 (INDIRECT_REF, cst_uchar_node,
- build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
- tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
- return expand_expr (result, target, mode, EXPAND_NORMAL);
- }
-
-#if defined HAVE_cmpmemsi || defined HAVE_cmpstrsi
+#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
{
+ tree arg1 = TREE_VALUE (arglist);
+ tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result;
rtx insn;
@@ -3197,12 +3592,12 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
else
#endif
-#ifdef HAVE_cmpstrsi
- if (HAVE_cmpstrsi)
- insn_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
+#ifdef HAVE_cmpstrnsi
+ if (HAVE_cmpstrnsi)
+ insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
else
#endif
- return 0;
+ return 0;
/* If we don't have POINTER_TYPE, call the function. */
if (arg1_align == 0 || arg2_align == 0)
@@ -3211,26 +3606,34 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
/* Make a place to write the result of the instruction. */
result = target;
if (! (result != 0
- && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
+ && REG_P (result) && GET_MODE (result) == insn_mode
&& REGNO (result) >= FIRST_PSEUDO_REGISTER))
result = gen_reg_rtx (insn_mode);
- arg1_rtx = get_memory_rtx (arg1);
- arg2_rtx = get_memory_rtx (arg2);
- arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+ arg1_rtx = get_memory_rtx (arg1, len);
+ arg2_rtx = get_memory_rtx (arg2, len);
+ arg3_rtx = expand_normal (len);
+
+ /* Set MEM_SIZE as appropriate. */
+ if (GET_CODE (arg3_rtx) == CONST_INT)
+ {
+ set_mem_size (arg1_rtx, arg3_rtx);
+ set_mem_size (arg2_rtx, arg3_rtx);
+ }
+
#ifdef HAVE_cmpmemsi
if (HAVE_cmpmemsi)
insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
GEN_INT (MIN (arg1_align, arg2_align)));
else
#endif
-#ifdef HAVE_cmpstrsi
- if (HAVE_cmpstrsi)
- insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
- GEN_INT (MIN (arg1_align, arg2_align)));
+#ifdef HAVE_cmpstrnsi
+ if (HAVE_cmpstrnsi)
+ insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
+ GEN_INT (MIN (arg1_align, arg2_align)));
else
#endif
- abort ();
+ gcc_unreachable ();
if (insn)
emit_insn (insn);
@@ -3240,7 +3643,7 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
XEXP (arg1_rtx, 0), Pmode,
XEXP (arg2_rtx, 0), Pmode,
convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
- TREE_UNSIGNED (sizetype)),
+ TYPE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
/* Return the value in the proper mode for this function. */
@@ -3268,139 +3671,146 @@ static rtx
expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
{
tree arglist = TREE_OPERAND (exp, 1);
- tree arg1, arg2;
- const char *p1, *p2;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
-
- arg1 = TREE_VALUE (arglist);
- arg2 = TREE_VALUE (TREE_CHAIN (arglist));
-
- /* If both arguments are equal (and not volatile), return zero. */
- if (operand_equal_p (arg1, arg2, 0))
- return const0_rtx;
-
- p1 = c_getstr (arg1);
- p2 = c_getstr (arg2);
-
- if (p1 && p2)
+ else
{
- const int i = strcmp (p1, p2);
- return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
+ tree result = fold_builtin_strcmp (arglist);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
- /* If either arg is "", return an expression corresponding to
- (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
- if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
+#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
+ if (cmpstr_optab[SImode] != CODE_FOR_nothing
+ || cmpstrn_optab[SImode] != CODE_FOR_nothing)
{
- tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
- tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
- tree ind1 =
- fold (build1 (CONVERT_EXPR, integer_type_node,
- build1 (INDIRECT_REF, cst_uchar_node,
- build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
- tree ind2 =
- fold (build1 (CONVERT_EXPR, integer_type_node,
- build1 (INDIRECT_REF, cst_uchar_node,
- build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
- tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
- return expand_expr (result, target, mode, EXPAND_NORMAL);
- }
-
-#ifdef HAVE_cmpstrsi
- if (HAVE_cmpstrsi)
- {
- tree len, len1, len2;
- rtx arg1_rtx, arg2_rtx, arg3_rtx;
- rtx result, insn;
- tree fndecl;
-
- int arg1_align
- = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
- int arg2_align
- = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
- enum machine_mode insn_mode
- = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
-
- len1 = c_strlen (arg1, 1);
- len2 = c_strlen (arg2, 1);
-
- if (len1)
- len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
- if (len2)
- len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
+ rtx arg1_rtx, arg2_rtx;
+ rtx result, insn = NULL_RTX;
+ tree fndecl, fn;
+
+ tree arg1 = TREE_VALUE (arglist);
+ tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
+ int arg1_align
+ = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
+ int arg2_align
+ = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
+
+ /* If we don't have POINTER_TYPE, call the function. */
+ if (arg1_align == 0 || arg2_align == 0)
+ return 0;
- /* If we don't have a constant length for the first, use the length
- of the second, if we know it. We don't require a constant for
- this case; some cost analysis could be done if both are available
- but neither is constant. For now, assume they're equally cheap,
- unless one has side effects. If both strings have constant lengths,
- use the smaller. */
+ /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
+ arg1 = builtin_save_expr (arg1);
+ arg2 = builtin_save_expr (arg2);
- if (!len1)
- len = len2;
- else if (!len2)
- len = len1;
- else if (TREE_SIDE_EFFECTS (len1))
- len = len2;
- else if (TREE_SIDE_EFFECTS (len2))
- len = len1;
- else if (TREE_CODE (len1) != INTEGER_CST)
- len = len2;
- else if (TREE_CODE (len2) != INTEGER_CST)
- len = len1;
- else if (tree_int_cst_lt (len1, len2))
- len = len1;
- else
- len = len2;
+ arg1_rtx = get_memory_rtx (arg1, NULL);
+ arg2_rtx = get_memory_rtx (arg2, NULL);
- /* If both arguments have side effects, we cannot optimize. */
- if (!len || TREE_SIDE_EFFECTS (len))
- return 0;
+#ifdef HAVE_cmpstrsi
+ /* Try to call cmpstrsi. */
+ if (HAVE_cmpstrsi)
+ {
+ enum machine_mode insn_mode
+ = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
+
+ /* Make a place to write the result of the instruction. */
+ result = target;
+ if (! (result != 0
+ && REG_P (result) && GET_MODE (result) == insn_mode
+ && REGNO (result) >= FIRST_PSEUDO_REGISTER))
+ result = gen_reg_rtx (insn_mode);
+
+ insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
+ GEN_INT (MIN (arg1_align, arg2_align)));
+ }
+#endif
+#ifdef HAVE_cmpstrnsi
+ /* Try to determine at least one length and call cmpstrnsi. */
+ if (!insn && HAVE_cmpstrnsi)
+ {
+ tree len;
+ rtx arg3_rtx;
+
+ enum machine_mode insn_mode
+ = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
+ tree len1 = c_strlen (arg1, 1);
+ tree len2 = c_strlen (arg2, 1);
+
+ if (len1)
+ len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
+ if (len2)
+ len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
+
+ /* If we don't have a constant length for the first, use the length
+ of the second, if we know it. We don't require a constant for
+ this case; some cost analysis could be done if both are available
+ but neither is constant. For now, assume they're equally cheap,
+ unless one has side effects. If both strings have constant lengths,
+ use the smaller. */
+
+ if (!len1)
+ len = len2;
+ else if (!len2)
+ len = len1;
+ else if (TREE_SIDE_EFFECTS (len1))
+ len = len2;
+ else if (TREE_SIDE_EFFECTS (len2))
+ len = len1;
+ else if (TREE_CODE (len1) != INTEGER_CST)
+ len = len2;
+ else if (TREE_CODE (len2) != INTEGER_CST)
+ len = len1;
+ else if (tree_int_cst_lt (len1, len2))
+ len = len1;
+ else
+ len = len2;
- /* If we don't have POINTER_TYPE, call the function. */
- if (arg1_align == 0 || arg2_align == 0)
- return 0;
+ /* If both arguments have side effects, we cannot optimize. */
+ if (!len || TREE_SIDE_EFFECTS (len))
+ goto do_libcall;
- /* Make a place to write the result of the instruction. */
- result = target;
- if (! (result != 0
- && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
- && REGNO (result) >= FIRST_PSEUDO_REGISTER))
- result = gen_reg_rtx (insn_mode);
+ arg3_rtx = expand_normal (len);
- /* Stabilize the arguments in case gen_cmpstrsi fails. */
- arg1 = save_expr (arg1);
- arg2 = save_expr (arg2);
+ /* Make a place to write the result of the instruction. */
+ result = target;
+ if (! (result != 0
+ && REG_P (result) && GET_MODE (result) == insn_mode
+ && REGNO (result) >= FIRST_PSEUDO_REGISTER))
+ result = gen_reg_rtx (insn_mode);
- arg1_rtx = get_memory_rtx (arg1);
- arg2_rtx = get_memory_rtx (arg2);
- arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
- insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
- GEN_INT (MIN (arg1_align, arg2_align)));
- if (insn)
- {
- emit_insn (insn);
+ insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
+ GEN_INT (MIN (arg1_align, arg2_align)));
+ }
+#endif
- /* Return the value in the proper mode for this function. */
- mode = TYPE_MODE (TREE_TYPE (exp));
- if (GET_MODE (result) == mode)
- return result;
- if (target == 0)
- return convert_to_mode (mode, result, 0);
- convert_move (target, result, 0);
- return target;
- }
+ if (insn)
+ {
+ emit_insn (insn);
+
+ /* Return the value in the proper mode for this function. */
+ mode = TYPE_MODE (TREE_TYPE (exp));
+ if (GET_MODE (result) == mode)
+ return result;
+ if (target == 0)
+ return convert_to_mode (mode, result, 0);
+ convert_move (target, result, 0);
+ return target;
+ }
- /* Expand the library call ourselves using a stabilized argument
- list to avoid re-evaluating the function's arguments twice. */
- arglist = build_tree_list (NULL_TREE, arg2);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
- fndecl = get_callee_fndecl (exp);
- exp = build_function_call_expr (fndecl, arglist);
- return expand_call (exp, target, target == const0_rtx);
- }
+ /* Expand the library call ourselves using a stabilized argument
+ list to avoid re-evaluating the function's arguments twice. */
+#ifdef HAVE_cmpstrnsi
+ do_libcall:
+#endif
+ arglist = build_tree_list (NULL_TREE, arg2);
+ arglist = tree_cons (NULL_TREE, arg1, arglist);
+ fndecl = get_callee_fndecl (exp);
+ fn = build_function_call_expr (fndecl, arglist);
+ if (TREE_CODE (fn) == CALL_EXPR)
+ CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+ return expand_call (fn, target, target == const0_rtx);
+ }
#endif
return 0;
}
@@ -3413,83 +3823,37 @@ static rtx
expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
{
tree arglist = TREE_OPERAND (exp, 1);
- tree arg1, arg2, arg3;
- const char *p1, *p2;
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
-
- arg1 = TREE_VALUE (arglist);
- arg2 = TREE_VALUE (TREE_CHAIN (arglist));
- arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
-
- /* If the len parameter is zero, return zero. */
- if (integer_zerop (arg3))
- {
- /* Evaluate and ignore arg1 and arg2 in case they have
- side-effects. */
- expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
- expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
-
- /* If arg1 and arg2 are equal (and not volatile), return zero. */
- if (operand_equal_p (arg1, arg2, 0))
- {
- /* Evaluate and ignore arg3 in case it has side-effects. */
- expand_expr (arg3, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
-
- p1 = c_getstr (arg1);
- p2 = c_getstr (arg2);
-
- /* If all arguments are constant, evaluate at compile-time. */
- if (host_integerp (arg3, 1) && p1 && p2)
- {
- const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
- return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
- }
-
- /* If len == 1 or (either string parameter is "" and (len >= 1)),
- return (*(const u_char*)arg1 - *(const u_char*)arg2). */
- if (host_integerp (arg3, 1)
- && (tree_low_cst (arg3, 1) == 1
- || (tree_low_cst (arg3, 1) > 1
- && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
+ else
{
- tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
- tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
- tree ind1 =
- fold (build1 (CONVERT_EXPR, integer_type_node,
- build1 (INDIRECT_REF, cst_uchar_node,
- build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
- tree ind2 =
- fold (build1 (CONVERT_EXPR, integer_type_node,
- build1 (INDIRECT_REF, cst_uchar_node,
- build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
- tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
- return expand_expr (result, target, mode, EXPAND_NORMAL);
+ tree result = fold_builtin_strncmp (arglist);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
/* If c_strlen can determine an expression for one of the string
- lengths, and it doesn't have side effects, then emit cmpstrsi
+ lengths, and it doesn't have side effects, then emit cmpstrnsi
using length MIN(strlen(string)+1, arg3). */
-#ifdef HAVE_cmpstrsi
- if (HAVE_cmpstrsi)
+#ifdef HAVE_cmpstrnsi
+ if (HAVE_cmpstrnsi)
{
+ tree arg1 = TREE_VALUE (arglist);
+ tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
tree len, len1, len2;
rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result, insn;
- tree fndecl;
+ tree fndecl, fn;
int arg1_align
= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
int arg2_align
= get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
enum machine_mode insn_mode
- = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
+ = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
len1 = c_strlen (arg1, 1);
len2 = c_strlen (arg2, 1);
@@ -3528,7 +3892,8 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
return 0;
/* The actual new length parameter is MIN(len,arg3). */
- len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
+ len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
+ fold_convert (TREE_TYPE (len), arg3));
/* If we don't have POINTER_TYPE, call the function. */
if (arg1_align == 0 || arg2_align == 0)
@@ -3537,20 +3902,20 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
/* Make a place to write the result of the instruction. */
result = target;
if (! (result != 0
- && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
+ && REG_P (result) && GET_MODE (result) == insn_mode
&& REGNO (result) >= FIRST_PSEUDO_REGISTER))
result = gen_reg_rtx (insn_mode);
- /* Stabilize the arguments in case gen_cmpstrsi fails. */
- arg1 = save_expr (arg1);
- arg2 = save_expr (arg2);
- len = save_expr (len);
+ /* Stabilize the arguments in case gen_cmpstrnsi fails. */
+ arg1 = builtin_save_expr (arg1);
+ arg2 = builtin_save_expr (arg2);
+ len = builtin_save_expr (len);
- arg1_rtx = get_memory_rtx (arg1);
- arg2_rtx = get_memory_rtx (arg2);
- arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
- insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
- GEN_INT (MIN (arg1_align, arg2_align)));
+ arg1_rtx = get_memory_rtx (arg1, len);
+ arg2_rtx = get_memory_rtx (arg2, len);
+ arg3_rtx = expand_normal (len);
+ insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
+ GEN_INT (MIN (arg1_align, arg2_align)));
if (insn)
{
emit_insn (insn);
@@ -3571,8 +3936,10 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
arglist = tree_cons (NULL_TREE, arg2, arglist);
arglist = tree_cons (NULL_TREE, arg1, arglist);
fndecl = get_callee_fndecl (exp);
- exp = build_function_call_expr (fndecl, arglist);
- return expand_call (exp, target, target == const0_rtx);
+ fn = build_function_call_expr (fndecl, arglist);
+ if (TREE_CODE (fn) == CALL_EXPR)
+ CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+ return expand_call (fn, target, target == const0_rtx);
}
#endif
return 0;
@@ -3583,61 +3950,61 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
otherwise try to get the result in TARGET, if convenient. */
static rtx
-expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
{
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
tree dst = TREE_VALUE (arglist),
- src = TREE_VALUE (TREE_CHAIN (arglist));
+ src = TREE_VALUE (TREE_CHAIN (arglist));
const char *p = c_getstr (src);
- if (p)
+ /* If the string length is zero, return the dst parameter. */
+ if (p && *p == '\0')
+ return expand_expr (dst, target, mode, EXPAND_NORMAL);
+
+ if (!optimize_size)
{
- /* If the string length is zero, return the dst parameter. */
- if (*p == '\0')
- return expand_expr (dst, target, mode, EXPAND_NORMAL);
- else if (!optimize_size)
+ /* See if we can store by pieces into (dst + strlen(dst)). */
+ tree newsrc, newdst,
+ strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+ rtx insns;
+
+ /* Stabilize the argument list. */
+ newsrc = builtin_save_expr (src);
+ if (newsrc != src)
+ arglist = build_tree_list (NULL_TREE, newsrc);
+ else
+ arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe. */
+
+ dst = builtin_save_expr (dst);
+
+ start_sequence ();
+
+ /* Create strlen (dst). */
+ newdst =
+ build_function_call_expr (strlen_fn,
+ build_tree_list (NULL_TREE, dst));
+ /* Create (dst + (cast) strlen (dst)). */
+ newdst = fold_convert (TREE_TYPE (dst), newdst);
+ newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
+
+ newdst = builtin_save_expr (newdst);
+ arglist = tree_cons (NULL_TREE, newdst, arglist);
+
+ if (!expand_builtin_strcpy (fndecl, arglist, target, mode))
{
- /* Otherwise if !optimize_size, see if we can store by
- pieces into (dst + strlen(dst)). */
- tree newdst, arglist,
- strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
-
- /* This is the length argument. */
- arglist = build_tree_list (NULL_TREE,
- fold (size_binop (PLUS_EXPR,
- c_strlen (src, 0),
- ssize_int (1))));
- /* Prepend src argument. */
- arglist = tree_cons (NULL_TREE, src, arglist);
-
- /* We're going to use dst more than once. */
- dst = save_expr (dst);
-
- /* Create strlen (dst). */
- newdst =
- fold (build_function_call_expr (strlen_fn,
- build_tree_list (NULL_TREE,
- dst)));
- /* Create (dst + strlen (dst)). */
- newdst = fold (build (PLUS_EXPR, TREE_TYPE (dst), dst, newdst));
-
- /* Prepend the new dst argument. */
- arglist = tree_cons (NULL_TREE, newdst, arglist);
-
- /* We don't want to get turned into a memcpy if the
- target is const0_rtx, i.e. when the return value
- isn't used. That would produce pessimized code so
- pass in a target of zero, it should never actually be
- used. If this was successful return the original
- dst, not the result of mempcpy. */
- if (expand_builtin_mempcpy (arglist, /*target=*/0, mode, /*endp=*/0))
- return expand_expr (dst, target, mode, EXPAND_NORMAL);
- else
- return 0;
+ end_sequence (); /* Stop sequence. */
+ return 0;
}
+
+ /* Output the entire sequence. */
+ insns = get_insns ();
+ end_sequence ();
+ emit_insn (insns);
+
+ return expand_expr (dst, target, mode, EXPAND_NORMAL);
}
return 0;
@@ -3651,46 +4018,14 @@ expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
static rtx
expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist,
- POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
- return 0;
- else
+ if (validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
- tree dst = TREE_VALUE (arglist),
- src = TREE_VALUE (TREE_CHAIN (arglist)),
- len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- const char *p = c_getstr (src);
-
- /* If the requested length is zero, or the src parameter string
- length is zero, return the dst parameter. */
- if (integer_zerop (len) || (p && *p == '\0'))
- {
- /* Evaluate and ignore the src and len parameters in case
- they have side-effects. */
- expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
- expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dst, target, mode, EXPAND_NORMAL);
- }
-
- /* If the requested len is greater than or equal to the string
- length, call strcat. */
- if (TREE_CODE (len) == INTEGER_CST && p
- && compare_tree_int (len, strlen (p)) >= 0)
- {
- tree newarglist
- = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
- tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
-
- /* If the replacement _DECL isn't initialized, don't do the
- transformation. */
- if (!fn)
- return 0;
-
- return expand_expr (build_function_call_expr (fn, newarglist),
- target, mode, EXPAND_NORMAL);
- }
- return 0;
+ tree result = fold_builtin_strncat (arglist);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
+ return 0;
}
/* Expand expression EXP, which is a call to the strspn builtin.
@@ -3700,31 +4035,13 @@ expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
static rtx
expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
- return 0;
- else
+ if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
- tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
- const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
-
- /* If both arguments are constants, evaluate at compile-time. */
- if (p1 && p2)
- {
- const size_t r = strspn (p1, p2);
- return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
- }
-
- /* If either argument is "", return 0. */
- if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
- {
- /* Evaluate and ignore both arguments in case either one has
- side-effects. */
- expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
- expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
- return 0;
+ tree result = fold_builtin_strspn (arglist);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
+ return 0;
}
/* Expand expression EXP, which is a call to the strcspn builtin.
@@ -3734,45 +4051,13 @@ expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
static rtx
expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
- return 0;
- else
+ if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
- tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
- const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
-
- /* If both arguments are constants, evaluate at compile-time. */
- if (p1 && p2)
- {
- const size_t r = strcspn (p1, p2);
- return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
- }
-
- /* If the first argument is "", return 0. */
- if (p1 && *p1 == '\0')
- {
- /* Evaluate and ignore argument s2 in case it has
- side-effects. */
- expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
-
- /* If the second argument is "", return __builtin_strlen(s1). */
- if (p2 && *p2 == '\0')
- {
- tree newarglist = build_tree_list (NULL_TREE, s1),
- fn = implicit_built_in_decls[BUILT_IN_STRLEN];
-
- /* If the replacement _DECL isn't initialized, don't do the
- transformation. */
- if (!fn)
- return 0;
-
- return expand_expr (build_function_call_expr (fn, newarglist),
- target, mode, EXPAND_NORMAL);
- }
- return 0;
+ tree result = fold_builtin_strcspn (arglist);
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
}
+ return 0;
}
/* Expand a call to __builtin_saveregs, generating the result in TARGET,
@@ -3806,7 +4091,7 @@ expand_builtin_saveregs (void)
is inside a start_sequence, make the outer-level insn chain current, so
the code is placed at the start of the function. */
push_topmost_sequence ();
- emit_insn_after (seq, get_insns ());
+ emit_insn_after (seq, entry_of_function ());
pop_topmost_sequence ();
return val;
@@ -3822,66 +4107,35 @@ expand_builtin_args_info (tree arglist)
int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
int *word_ptr = (int *) &current_function_args_info;
- if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
- abort ();
+ gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
if (arglist != 0)
{
if (!host_integerp (TREE_VALUE (arglist), 0))
- error ("argument of `__builtin_args_info' must be constant");
+ error ("argument of %<__builtin_args_info%> must be constant");
else
{
HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
if (wordnum < 0 || wordnum >= nwords)
- error ("argument of `__builtin_args_info' out of range");
+ error ("argument of %<__builtin_args_info%> out of range");
else
return GEN_INT (word_ptr[wordnum]);
}
}
else
- error ("missing argument in `__builtin_args_info'");
+ error ("missing argument in %<__builtin_args_info%>");
return const0_rtx;
}
-/* Expand ARGLIST, from a call to __builtin_next_arg. */
+/* Expand a call to __builtin_next_arg. */
static rtx
-expand_builtin_next_arg (tree arglist)
+expand_builtin_next_arg (void)
{
- tree fntype = TREE_TYPE (current_function_decl);
-
- if (TYPE_ARG_TYPES (fntype) == 0
- || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
- == void_type_node))
- {
- error ("`va_start' used in function with fixed args");
- return const0_rtx;
- }
-
- if (arglist)
- {
- tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
- tree arg = TREE_VALUE (arglist);
-
- /* Strip off all nops for the sake of the comparison. This
- is not quite the same as STRIP_NOPS. It does more.
- We must also strip off INDIRECT_EXPR for C++ reference
- parameters. */
- while (TREE_CODE (arg) == NOP_EXPR
- || TREE_CODE (arg) == CONVERT_EXPR
- || TREE_CODE (arg) == NON_LVALUE_EXPR
- || TREE_CODE (arg) == INDIRECT_REF)
- arg = TREE_OPERAND (arg, 0);
- if (arg != last_parm)
- warning ("second parameter of `va_start' not last named argument");
- }
- else
- /* Evidently an out of date version of <stdarg.h>; can't validate
- va_start's second argument, but can still work as intended. */
- warning ("`__builtin_next_arg' called without an argument");
-
+ /* Checking arguments is already done in fold_builtin_next_arg
+ that must be called before this function. */
return expand_binop (Pmode, add_optab,
current_function_internal_arg_pointer,
current_function_arg_offset_rtx,
@@ -3906,10 +4160,7 @@ stabilize_va_list (tree valist, int needs_lvalue)
if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
{
tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
- tree p2 = build_pointer_type (va_list_type_node);
-
- valist = build1 (ADDR_EXPR, p2, valist);
- valist = fold (build1 (NOP_EXPR, p1, valist));
+ valist = build_fold_addr_expr_with_type (valist, p1);
}
}
else
@@ -3922,14 +4173,13 @@ stabilize_va_list (tree valist, int needs_lvalue)
return valist;
pt = build_pointer_type (va_list_type_node);
- valist = fold (build1 (ADDR_EXPR, pt, valist));
+ valist = fold_build1 (ADDR_EXPR, pt, valist);
TREE_SIDE_EFFECTS (valist) = 1;
}
if (TREE_SIDE_EFFECTS (valist))
valist = save_expr (valist);
- valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
- valist));
+ valist = build_fold_indirect_ref (valist);
}
return valist;
@@ -3951,8 +4201,8 @@ std_expand_builtin_va_start (tree valist, rtx nextarg)
{
tree t;
- t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
- make_tree (ptr_type_node, nextarg));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
+ make_tree (ptr_type_node, nextarg));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
@@ -3968,10 +4218,16 @@ expand_builtin_va_start (tree arglist)
chain = TREE_CHAIN (arglist);
- if (TREE_CHAIN (chain))
- error ("too many arguments to function `va_start'");
+ if (!chain)
+ {
+ error ("too few arguments to function %<va_start%>");
+ return const0_rtx;
+ }
- nextarg = expand_builtin_next_arg (chain);
+ if (fold_builtin_next_arg (chain))
+ return const0_rtx;
+
+ nextarg = expand_builtin_next_arg ();
valist = stabilize_va_list (TREE_VALUE (arglist), 1);
#ifdef EXPAND_BUILTIN_VA_START
@@ -3986,180 +4242,211 @@ expand_builtin_va_start (tree arglist)
/* The "standard" implementation of va_arg: read the value from the
current (padded) address and increment by the (padded) size. */
-rtx
-std_expand_builtin_va_arg (tree valist, tree type)
+tree
+std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
{
- tree addr_tree, t, type_size = NULL;
- tree align, alignm1;
- tree rounded_size;
- rtx addr;
- HOST_WIDE_INT boundary;
+ tree addr, t, type_size, rounded_size, valist_tmp;
+ unsigned HOST_WIDE_INT align, boundary;
+ bool indirect;
+
+#ifdef ARGS_GROW_DOWNWARD
+ /* All of the alignment and movement below is for args-grow-up machines.
+ As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
+ implement their own specialized gimplify_va_arg_expr routines. */
+ gcc_unreachable ();
+#endif
- /* Compute the rounded size of the type. */
- align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
- alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
- boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
+ indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+ if (indirect)
+ type = build_pointer_type (type);
+
+ align = PARM_BOUNDARY / BITS_PER_UNIT;
+ boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type) / BITS_PER_UNIT;
+
+ /* Hoist the valist value into a temporary for the moment. */
+ valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
/* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
requires greater alignment, we must perform dynamic alignment. */
-
- if (boundary > PARM_BOUNDARY)
+ if (boundary > align
+ && !integer_zerop (TYPE_SIZE (type)))
{
- if (!PAD_VARARGS_DOWN)
- {
- t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
- build (PLUS_EXPR, TREE_TYPE (valist), valist,
- build_int_2 (boundary / BITS_PER_UNIT - 1, 0)));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
- t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
- build (BIT_AND_EXPR, TREE_TYPE (valist), valist,
- build_int_2 (~(boundary / BITS_PER_UNIT - 1), -1)));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+ build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
+ gimplify_and_add (t, pre_p);
+
+ t = fold_convert (TREE_TYPE (valist), size_int (-boundary));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+ build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t));
+ gimplify_and_add (t, pre_p);
}
- if (type == error_mark_node
- || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
- || TREE_OVERFLOW (type_size))
- rounded_size = size_zero_node;
else
- rounded_size = fold (build (MULT_EXPR, sizetype,
- fold (build (TRUNC_DIV_EXPR, sizetype,
- fold (build (PLUS_EXPR, sizetype,
- type_size, alignm1)),
- align)),
- align));
+ boundary = align;
- /* Get AP. */
- addr_tree = valist;
- if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
+ /* If the actual alignment is less than the alignment of the type,
+ adjust the type accordingly so that we don't assume strict alignment
+ when deferencing the pointer. */
+ boundary *= BITS_PER_UNIT;
+ if (boundary < TYPE_ALIGN (type))
{
- /* Small args are padded downward. */
- addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
- fold (build (COND_EXPR, sizetype,
- fold (build (GT_EXPR, sizetype,
- rounded_size,
- align)),
- size_zero_node,
- fold (build (MINUS_EXPR, sizetype,
- rounded_size,
- type_size))))));
+ type = build_variant_type_copy (type);
+ TYPE_ALIGN (type) = boundary;
}
- addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
- addr = copy_to_reg (addr);
+ /* Compute the rounded size of the type. */
+ type_size = size_in_bytes (type);
+ rounded_size = round_up (type_size, align);
- /* Compute new value for AP. */
- if (! integer_zerop (rounded_size))
+ /* Reduce rounded_size so it's sharable with the postqueue. */
+ gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
+
+ /* Get AP. */
+ addr = valist_tmp;
+ if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
{
- t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
- build (PLUS_EXPR, TREE_TYPE (valist), valist,
- rounded_size));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ /* Small args are padded downward. */
+ t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
+ t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
+ size_binop (MINUS_EXPR, rounded_size, type_size));
+ t = fold_convert (TREE_TYPE (addr), t);
+ addr = fold_build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t);
}
+ /* Compute new value for AP. */
+ t = fold_convert (TREE_TYPE (valist), rounded_size);
+ t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+ gimplify_and_add (t, pre_p);
+
+ addr = fold_convert (build_pointer_type (type), addr);
+
+ if (indirect)
+ addr = build_va_arg_indirect_ref (addr);
+
+ return build_va_arg_indirect_ref (addr);
+}
+
+/* Build an indirect-ref expression over the given TREE, which represents a
+ piece of a va_arg() expansion. */
+tree
+build_va_arg_indirect_ref (tree addr)
+{
+ addr = build_fold_indirect_ref (addr);
+
+ if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
+ mf_mark (addr);
+
return addr;
}
-/* Expand __builtin_va_arg, which is not really a builtin function, but
- a very special sort of operator. */
+/* Return a dummy expression of type TYPE in order to keep going after an
+ error. */
-rtx
-expand_builtin_va_arg (tree valist, tree type)
+static tree
+dummy_object (tree type)
+{
+ tree t = build_int_cst (build_pointer_type (type), 0);
+ return build1 (INDIRECT_REF, type, t);
+}
+
+/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
+ builtin function, but a very special sort of operator. */
+
+enum gimplify_status
+gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
{
- rtx addr, result;
tree promoted_type, want_va_type, have_va_type;
+ tree valist = TREE_OPERAND (*expr_p, 0);
+ tree type = TREE_TYPE (*expr_p);
+ tree t;
/* Verify that valist is of the proper type. */
-
want_va_type = va_list_type_node;
have_va_type = TREE_TYPE (valist);
+
+ if (have_va_type == error_mark_node)
+ return GS_ERROR;
+
if (TREE_CODE (want_va_type) == ARRAY_TYPE)
{
/* If va_list is an array type, the argument may have decayed
to a pointer type, e.g. by being passed to another function.
- In that case, unwrap both types so that we can compare the
+ In that case, unwrap both types so that we can compare the
underlying records. */
if (TREE_CODE (have_va_type) == ARRAY_TYPE
- || TREE_CODE (have_va_type) == POINTER_TYPE)
+ || POINTER_TYPE_P (have_va_type))
{
want_va_type = TREE_TYPE (want_va_type);
have_va_type = TREE_TYPE (have_va_type);
}
}
+
if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
{
- error ("first argument to `va_arg' not of type `va_list'");
- addr = const0_rtx;
+ error ("first argument to %<va_arg%> not of type %<va_list%>");
+ return GS_ERROR;
}
/* Generate a diagnostic for requesting data of a type that cannot
be passed through `...' due to type promotion at the call site. */
- else if ((promoted_type = (*lang_hooks.types.type_promotes_to) (type))
+ else if ((promoted_type = lang_hooks.types.type_promotes_to (type))
!= type)
{
- const char *name = "<anonymous type>", *pname = 0;
static bool gave_help;
- if (TYPE_NAME (type))
- {
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- name = IDENTIFIER_POINTER (TYPE_NAME (type));
- else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && DECL_NAME (TYPE_NAME (type)))
- name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
- }
- if (TYPE_NAME (promoted_type))
- {
- if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
- pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
- else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
- && DECL_NAME (TYPE_NAME (promoted_type)))
- pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
- }
-
/* Unfortunately, this is merely undefined, rather than a constraint
violation, so we cannot make this an error. If this call is never
executed, the program is still strictly conforming. */
- warning ("`%s' is promoted to `%s' when passed through `...'",
- name, pname);
+ warning (0, "%qT is promoted to %qT when passed through %<...%>",
+ type, promoted_type);
if (! gave_help)
{
gave_help = true;
- warning ("(so you should pass `%s' not `%s' to `va_arg')",
- pname, name);
+ warning (0, "(so you should pass %qT not %qT to %<va_arg%>)",
+ promoted_type, type);
}
/* We can, however, treat "undefined" any way we please.
Call abort to encourage the user to fix the program. */
inform ("if this code is reached, the program will abort");
- expand_builtin_trap ();
+ t = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
+ NULL);
+ append_to_statement_list (t, pre_p);
/* This is dead code, but go ahead and finish so that the
mode of the result comes out right. */
- addr = const0_rtx;
+ *expr_p = dummy_object (type);
+ return GS_ALL_DONE;
}
else
{
/* Make it easier for the backends by protecting the valist argument
- from multiple evaluations. */
- valist = stabilize_va_list (valist, 0);
-
-#ifdef EXPAND_BUILTIN_VA_ARG
- addr = EXPAND_BUILTIN_VA_ARG (valist, type);
-#else
- addr = std_expand_builtin_va_arg (valist, type);
-#endif
- }
-
- addr = convert_memory_address (Pmode, addr);
+ from multiple evaluations. */
+ if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
+ {
+ /* For this case, the backends will be expecting a pointer to
+ TREE_TYPE (va_list_type_node), but it's possible we've
+ actually been given an array (an actual va_list_type_node).
+ So fix it. */
+ if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
+ {
+ tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
+ valist = build_fold_addr_expr_with_type (valist, p1);
+ }
+ gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
+ }
+ else
+ gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
- result = gen_rtx_MEM (TYPE_MODE (type), addr);
- set_mem_alias_set (result, get_varargs_alias_set ());
+ if (!targetm.gimplify_va_arg_expr)
+ /* FIXME:Once most targets are converted we should merely
+ assert this is non-null. */
+ return GS_ALL_DONE;
- return result;
+ *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
+ return GS_OK;
+ }
}
/* Expand ARGLIST, from a call to __builtin_va_end. */
@@ -4194,7 +4481,7 @@ expand_builtin_va_copy (tree arglist)
if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
{
- t = build (MODIFY_EXPR, va_list_type_node, dst, src);
+ t = build2 (MODIFY_EXPR, va_list_type_node, dst, src);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
@@ -4241,25 +4528,24 @@ expand_builtin_frame_address (tree fndecl, tree arglist)
else if (! host_integerp (TREE_VALUE (arglist), 1))
{
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
- error ("invalid arg to `__builtin_frame_address'");
+ error ("invalid argument to %<__builtin_frame_address%>");
else
- error ("invalid arg to `__builtin_return_address'");
+ error ("invalid argument to %<__builtin_return_address%>");
return const0_rtx;
}
else
{
rtx tem
= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
- tree_low_cst (TREE_VALUE (arglist), 1),
- hard_frame_pointer_rtx);
+ tree_low_cst (TREE_VALUE (arglist), 1));
/* Some ports cannot access arbitrary stack frames. */
if (tem == NULL)
{
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
- warning ("unsupported arg to `__builtin_frame_address'");
+ warning (0, "unsupported argument to %<__builtin_frame_address%>");
else
- warning ("unsupported arg to `__builtin_return_address'");
+ warning (0, "unsupported argument to %<__builtin_return_address%>");
return const0_rtx;
}
@@ -4267,7 +4553,7 @@ expand_builtin_frame_address (tree fndecl, tree arglist)
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
return tem;
- if (GET_CODE (tem) != REG
+ if (!REG_P (tem)
&& ! CONSTANT_P (tem))
tem = copy_to_mode_reg (Pmode, tem);
return tem;
@@ -4284,11 +4570,17 @@ expand_builtin_alloca (tree arglist, rtx target)
rtx op0;
rtx result;
+ /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
+ should always expand to function calls. These can be intercepted
+ in libmudflap. */
+ if (flag_mudflap)
+ return 0;
+
if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
return 0;
/* Compute the argument. */
- op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (TREE_VALUE (arglist));
/* Allocate the desired space. */
result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
@@ -4316,8 +4608,7 @@ expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
Set TARGET to wherever the result comes back. */
target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
op_optab, op0, target, 1);
- if (target == 0)
- abort ();
+ gcc_assert (target);
return convert_to_mode (target_mode, target, 0);
}
@@ -4328,83 +4619,15 @@ expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
static rtx
expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
{
- tree len, fn;
- /* If we're using an unlocked function, assume the other unlocked
- functions exist explicitly. */
- tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
- : implicit_built_in_decls[BUILT_IN_FPUTC];
- tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
- : implicit_built_in_decls[BUILT_IN_FWRITE];
-
- /* If the return value is used, don't do the transformation. */
- if (target != const0_rtx)
- return 0;
-
/* Verify the arguments in the original call. */
- if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
- return 0;
-
- /* Get the length of the string passed to fputs. If the length
- can't be determined, punt. */
- if (!(len = c_strlen (TREE_VALUE (arglist), 1))
- || TREE_CODE (len) != INTEGER_CST)
- return 0;
-
- switch (compare_tree_int (len, 1))
+ if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
- case -1: /* length is 0, delete the call entirely . */
- {
- /* Evaluate and ignore the argument in case it has
- side-effects. */
- expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
- VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
- case 0: /* length is 1, call fputc. */
- {
- const char *p = c_getstr (TREE_VALUE (arglist));
-
- if (p != NULL)
- {
- /* New argument list transforming fputs(string, stream) to
- fputc(string[0], stream). */
- arglist =
- build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
- arglist =
- tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
- fn = fn_fputc;
- break;
- }
- }
- /* Fall through. */
- case 1: /* length is greater than 1, call fwrite. */
- {
- tree string_arg;
-
- /* If optimizing for size keep fputs. */
- if (optimize_size)
- return 0;
- string_arg = TREE_VALUE (arglist);
- /* New argument list transforming fputs(string, stream) to
- fwrite(string, 1, len, stream). */
- arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
- arglist = tree_cons (NULL_TREE, len, arglist);
- arglist = tree_cons (NULL_TREE, size_one_node, arglist);
- arglist = tree_cons (NULL_TREE, string_arg, arglist);
- fn = fn_fwrite;
- break;
- }
- default:
- abort ();
+ tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
+ unlocked, NULL_TREE);
+ if (result)
+ return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
}
-
- /* If the replacement _DECL isn't initialized, don't do the
- transformation. */
- if (!fn)
- return 0;
-
- return expand_expr (build_function_call_expr (fn, arglist),
- const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return 0;
}
/* Expand a call to __builtin_expect. We return our argument and emit a
@@ -4425,7 +4648,7 @@ expand_builtin_expect (tree arglist, rtx target)
if (TREE_CODE (c) != INTEGER_CST)
{
- error ("second arg to `__builtin_expect' must be a constant");
+ error ("second argument to %<__builtin_expect%> must be a constant");
c = integer_zero_node;
}
@@ -4476,9 +4699,9 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
ret = get_insns ();
drop_through_label = get_last_insn ();
- if (drop_through_label && GET_CODE (drop_through_label) == NOTE)
+ if (drop_through_label && NOTE_P (drop_through_label))
drop_through_label = prev_nonnote_insn (drop_through_label);
- if (drop_through_label && GET_CODE (drop_through_label) != CODE_LABEL)
+ if (drop_through_label && !LABEL_P (drop_through_label))
drop_through_label = NULL_RTX;
end_sequence ();
@@ -4493,7 +4716,7 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
{
rtx next = NEXT_INSN (insn);
- if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn))
+ if (JUMP_P (insn) && any_condjump_p (insn))
{
rtx ifelse = SET_SRC (pc_set (insn));
rtx then_dest = XEXP (ifelse, 1);
@@ -4516,10 +4739,10 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
/* Otherwise check where we drop through. */
else if (else_dest == pc_rtx)
{
- if (next && GET_CODE (next) == NOTE)
+ if (next && NOTE_P (next))
next = next_nonnote_insn (next);
- if (next && GET_CODE (next) == JUMP_INSN
+ if (next && JUMP_P (next)
&& any_uncondjump_p (next))
temp = XEXP (SET_SRC (pc_set (next)), 0);
else
@@ -4534,10 +4757,10 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
}
else if (then_dest == pc_rtx)
{
- if (next && GET_CODE (next) == NOTE)
+ if (next && NOTE_P (next))
next = next_nonnote_insn (next);
- if (next && GET_CODE (next) == JUMP_INSN
+ if (next && JUMP_P (next)
&& any_uncondjump_p (next))
temp = XEXP (SET_SRC (pc_set (next)), 0);
else
@@ -4555,7 +4778,7 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
probabilities. */
if (integer_zerop (arg1))
taken = 1 - taken;
- predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
+ predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
}
}
@@ -4600,43 +4823,43 @@ expand_builtin_fabs (tree arglist, rtx target, rtx subtarget)
return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
}
-/* Expand a call to cabs, cabsf or cabsl with arguments ARGLIST.
- Return 0 if a normal call should be emitted rather than expanding
- the function inline. If convenient, the result should be placed
- in target. */
+/* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST.
+ Return NULL is a normal call should be emitted rather than expanding the
+ function inline. If convenient, the result should be placed in TARGET.
+ SUBTARGET may be used as the target for computing the operand. */
static rtx
-expand_builtin_cabs (tree arglist, rtx target)
+expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
{
- enum machine_mode mode;
+ rtx op0, op1;
tree arg;
- rtx op0;
- if (arglist == 0 || TREE_CHAIN (arglist))
+ if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
return 0;
+
arg = TREE_VALUE (arglist);
- if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
- || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
- return 0;
+ op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
- mode = TYPE_MODE (TREE_TYPE (arg));
- op0 = expand_expr (arg, NULL_RTX, VOIDmode, 0);
- return expand_complex_abs (mode, op0, target, 0);
+ arg = TREE_VALUE (TREE_CHAIN (arglist));
+ op1 = expand_normal (arg);
+
+ return expand_copysign (op0, op1, target);
}
/* Create a new constant string literal and return a char* pointer to it.
The STRING_CST value is the LEN characters at STR. */
-static tree
+tree
build_string_literal (int len, const char *str)
{
tree t, elem, index, type;
t = build_string (len, str);
elem = build_type_variant (char_type_node, 1, 0);
- index = build_index_type (build_int_2 (len - 1, 0));
+ index = build_index_type (build_int_cst (NULL_TREE, len - 1));
type = build_array_type (elem, index);
TREE_TYPE (t) = type;
TREE_CONSTANT (t) = 1;
+ TREE_INVARIANT (t) = 1;
TREE_READONLY (t) = 1;
TREE_STATIC (t) = 1;
@@ -4648,15 +4871,16 @@ build_string_literal (int len, const char *str)
return t;
}
-/* Expand a call to printf or printf_unlocked with argument list ARGLIST.
+/* Expand EXP, a call to printf or printf_unlocked.
Return 0 if a normal call should be emitted rather than transforming
the function inline. If convenient, the result should be placed in
- TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
+ TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
call. */
static rtx
-expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
+expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
bool unlocked)
{
+ tree arglist = TREE_OPERAND (exp, 1);
/* If we're using an unlocked function, assume the other unlocked
functions exist explicitly. */
tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
@@ -4674,7 +4898,7 @@ expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
if (! arglist)
return 0;
fmt = TREE_VALUE (arglist);
- if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
+ if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
arglist = TREE_CHAIN (arglist);
@@ -4683,17 +4907,20 @@ expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
if (fmt_str == NULL)
return 0;
+ if (!init_target_chars())
+ return 0;
+
/* If the format specifier was "%s\n", call __builtin_puts(arg). */
- if (strcmp (fmt_str, "%s\n") == 0)
+ if (strcmp (fmt_str, target_percent_s_newline) == 0)
{
if (! arglist
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
+ || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
|| TREE_CHAIN (arglist))
return 0;
fn = fn_puts;
}
/* If the format specifier was "%c", call __builtin_putchar(arg). */
- else if (strcmp (fmt_str, "%c") == 0)
+ else if (strcmp (fmt_str, target_percent_c) == 0)
{
if (! arglist
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
@@ -4704,8 +4931,8 @@ expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
else
{
/* We can't handle anything else with % args or %% ... yet. */
- if (strchr (fmt_str, '%'))
- return 0;
+ if (strchr (fmt_str, target_percent))
+ return 0;
if (arglist)
return 0;
@@ -4719,7 +4946,7 @@ expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
/* Given printf("c"), (where c is any one character,)
convert "c"[0] to an int and pass that to the replacement
function. */
- arg = build_int_2 (fmt_str[0], 0);
+ arg = build_int_cst (NULL_TREE, fmt_str[0]);
arglist = build_tree_list (NULL_TREE, arg);
fn = fn_putchar;
}
@@ -4727,11 +4954,11 @@ expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
{
/* If the format specifier was "string\n", call puts("string"). */
size_t len = strlen (fmt_str);
- if (fmt_str[len - 1] == '\n')
+ if ((unsigned char)fmt_str[len - 1] == target_newline)
{
/* Create a NUL-terminated string that's one char shorter
than the original, stripping off the trailing '\n'. */
- char *newstr = (char *) alloca (len);
+ char *newstr = alloca (len);
memcpy (newstr, fmt_str, len - 1);
newstr[len - 1] = 0;
@@ -4748,19 +4975,22 @@ expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
if (!fn)
return 0;
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ fn = build_function_call_expr (fn, arglist);
+ if (TREE_CODE (fn) == CALL_EXPR)
+ CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+ return expand_expr (fn, target, mode, EXPAND_NORMAL);
}
-/* Expand a call to fprintf or fprintf_unlocked with argument list ARGLIST.
+/* Expand EXP, a call to fprintf or fprintf_unlocked.
Return 0 if a normal call should be emitted rather than transforming
the function inline. If convenient, the result should be placed in
- TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
+ TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
call. */
static rtx
-expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
- bool unlocked)
+expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
+ bool unlocked)
{
+ tree arglist = TREE_OPERAND (exp, 1);
/* If we're using an unlocked function, assume the other unlocked
functions exist explicitly. */
tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
@@ -4778,13 +5008,13 @@ expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
if (! arglist)
return 0;
fp = TREE_VALUE (arglist);
- if (TREE_CODE (TREE_TYPE (fp)) != POINTER_TYPE)
+ if (! POINTER_TYPE_P (TREE_TYPE (fp)))
return 0;
arglist = TREE_CHAIN (arglist);
if (! arglist)
return 0;
fmt = TREE_VALUE (arglist);
- if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
+ if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
arglist = TREE_CHAIN (arglist);
@@ -4793,11 +5023,14 @@ expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
if (fmt_str == NULL)
return 0;
+ if (!init_target_chars())
+ return 0;
+
/* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
- if (strcmp (fmt_str, "%s") == 0)
+ if (strcmp (fmt_str, target_percent_s) == 0)
{
if (! arglist
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
+ || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
|| TREE_CHAIN (arglist))
return 0;
arg = TREE_VALUE (arglist);
@@ -4806,7 +5039,7 @@ expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
fn = fn_fputs;
}
/* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
- else if (strcmp (fmt_str, "%c") == 0)
+ else if (strcmp (fmt_str, target_percent_c) == 0)
{
if (! arglist
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
@@ -4820,8 +5053,8 @@ expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
else
{
/* We can't handle anything else with % args or %% ... yet. */
- if (strchr (fmt_str, '%'))
- return 0;
+ if (strchr (fmt_str, target_percent))
+ return 0;
if (arglist)
return 0;
@@ -4844,8 +5077,10 @@ expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
if (!fn)
return 0;
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ fn = build_function_call_expr (fn, arglist);
+ if (TREE_CODE (fn) == CALL_EXPR)
+ CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+ return expand_expr (fn, target, mode, EXPAND_NORMAL);
}
/* Expand a call to sprintf with argument list ARGLIST. Return 0 if
@@ -4865,13 +5100,13 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
if (! arglist)
return 0;
dest = TREE_VALUE (arglist);
- if (TREE_CODE (TREE_TYPE (dest)) != POINTER_TYPE)
+ if (! POINTER_TYPE_P (TREE_TYPE (dest)))
return 0;
arglist = TREE_CHAIN (arglist);
if (! arglist)
return 0;
fmt = TREE_VALUE (arglist);
- if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
+ if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
arglist = TREE_CHAIN (arglist);
@@ -4880,8 +5115,11 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
if (fmt_str == NULL)
return 0;
+ if (!init_target_chars())
+ return 0;
+
/* If the format doesn't contain % args or %%, use strcpy. */
- if (strchr (fmt_str, '%') == 0)
+ if (strchr (fmt_str, target_percent) == 0)
{
tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
tree exp;
@@ -4892,12 +5130,11 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
const0_rtx, VOIDmode, EXPAND_NORMAL);
if (target == const0_rtx)
return const0_rtx;
- exp = build_int_2 (strlen (fmt_str), 0);
- exp = fold (build1 (NOP_EXPR, integer_type_node, exp));
+ exp = build_int_cst (NULL_TREE, strlen (fmt_str));
return expand_expr (exp, target, mode, EXPAND_NORMAL);
}
/* If the format is "%s", use strcpy if the result isn't used. */
- else if (strcmp (fmt_str, "%s") == 0)
+ else if (strcmp (fmt_str, target_percent_s) == 0)
{
tree fn, arg, len;
fn = implicit_built_in_decls[BUILT_IN_STRCPY];
@@ -4908,7 +5145,7 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
if (! arglist || TREE_CHAIN (arglist))
return 0;
arg = TREE_VALUE (arglist);
- if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
+ if (! POINTER_TYPE_P (TREE_TYPE (arg)))
return 0;
if (target != const0_rtx)
@@ -4932,6 +5169,472 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
return 0;
}
+
+/* Expand a call to either the entry or exit function profiler. */
+
+static rtx
+expand_builtin_profile_func (bool exitp)
+{
+ rtx this, which;
+
+ this = DECL_RTL (current_function_decl);
+ gcc_assert (MEM_P (this));
+ this = XEXP (this, 0);
+
+ if (exitp)
+ which = profile_function_exit_libfunc;
+ else
+ which = profile_function_entry_libfunc;
+
+ emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
+ expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
+ 0),
+ Pmode);
+
+ return const0_rtx;
+}
+
+/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
+
+static rtx
+round_trampoline_addr (rtx tramp)
+{
+ rtx temp, addend, mask;
+
+ /* If we don't need too much alignment, we'll have been guaranteed
+ proper alignment by get_trampoline_type. */
+ if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
+ return tramp;
+
+ /* Round address up to desired boundary. */
+ temp = gen_reg_rtx (Pmode);
+ addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
+ mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
+
+ temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
+ temp, 0, OPTAB_LIB_WIDEN);
+ tramp = expand_simple_binop (Pmode, AND, temp, mask,
+ temp, 0, OPTAB_LIB_WIDEN);
+
+ return tramp;
+}
+
+static rtx
+expand_builtin_init_trampoline (tree arglist)
+{
+ tree t_tramp, t_func, t_chain;
+ rtx r_tramp, r_func, r_chain;
+#ifdef TRAMPOLINE_TEMPLATE
+ rtx blktramp;
+#endif
+
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE,
+ POINTER_TYPE, VOID_TYPE))
+ return NULL_RTX;
+
+ t_tramp = TREE_VALUE (arglist);
+ arglist = TREE_CHAIN (arglist);
+ t_func = TREE_VALUE (arglist);
+ arglist = TREE_CHAIN (arglist);
+ t_chain = TREE_VALUE (arglist);
+
+ r_tramp = expand_normal (t_tramp);
+ r_func = expand_normal (t_func);
+ r_chain = expand_normal (t_chain);
+
+ /* Generate insns to initialize the trampoline. */
+ r_tramp = round_trampoline_addr (r_tramp);
+#ifdef TRAMPOLINE_TEMPLATE
+ blktramp = gen_rtx_MEM (BLKmode, r_tramp);
+ set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
+ emit_block_move (blktramp, assemble_trampoline_template (),
+ GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+#endif
+ trampolines_created = 1;
+ INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
+
+ return const0_rtx;
+}
+
+static rtx
+expand_builtin_adjust_trampoline (tree arglist)
+{
+ rtx tramp;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
+ return NULL_RTX;
+
+ tramp = expand_normal (TREE_VALUE (arglist));
+ tramp = round_trampoline_addr (tramp);
+#ifdef TRAMPOLINE_ADJUST_ADDRESS
+ TRAMPOLINE_ADJUST_ADDRESS (tramp);
+#endif
+
+ return tramp;
+}
+
+/* Expand a call to the built-in signbit, signbitf or signbitl function.
+ Return NULL_RTX if a normal call should be emitted rather than expanding
+ the function in-line. EXP is the expression that is a call to the builtin
+ function; if convenient, the result should be placed in TARGET. */
+
+static rtx
+expand_builtin_signbit (tree exp, rtx target)
+{
+ const struct real_format *fmt;
+ enum machine_mode fmode, imode, rmode;
+ HOST_WIDE_INT hi, lo;
+ tree arg, arglist;
+ int word, bitpos;
+ rtx temp;
+
+ arglist = TREE_OPERAND (exp, 1);
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return 0;
+
+ arg = TREE_VALUE (arglist);
+ fmode = TYPE_MODE (TREE_TYPE (arg));
+ rmode = TYPE_MODE (TREE_TYPE (exp));
+ fmt = REAL_MODE_FORMAT (fmode);
+
+ /* For floating point formats without a sign bit, implement signbit
+ as "ARG < 0.0". */
+ bitpos = fmt->signbit_ro;
+ if (bitpos < 0)
+ {
+ /* But we can't do this if the format supports signed zero. */
+ if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
+ return 0;
+
+ arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
+ build_real (TREE_TYPE (arg), dconst0));
+ return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
+ }
+
+ temp = expand_normal (arg);
+ if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
+ {
+ imode = int_mode_for_mode (fmode);
+ if (imode == BLKmode)
+ return 0;
+ temp = gen_lowpart (imode, temp);
+ }
+ else
+ {
+ imode = word_mode;
+ /* Handle targets with different FP word orders. */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
+ else
+ word = bitpos / BITS_PER_WORD;
+ temp = operand_subword_force (temp, word, fmode);
+ bitpos = bitpos % BITS_PER_WORD;
+ }
+
+ /* Force the intermediate word_mode (or narrower) result into a
+ register. This avoids attempting to create paradoxical SUBREGs
+ of floating point modes below. */
+ temp = force_reg (imode, temp);
+
+ /* If the bitpos is within the "result mode" lowpart, the operation
+ can be implement with a single bitwise AND. Otherwise, we need
+ a right shift and an AND. */
+
+ if (bitpos < GET_MODE_BITSIZE (rmode))
+ {
+ if (bitpos < HOST_BITS_PER_WIDE_INT)
+ {
+ hi = 0;
+ lo = (HOST_WIDE_INT) 1 << bitpos;
+ }
+ else
+ {
+ hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
+ lo = 0;
+ }
+
+ if (imode != rmode)
+ temp = gen_lowpart (rmode, temp);
+ temp = expand_binop (rmode, and_optab, temp,
+ immed_double_const (lo, hi, rmode),
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ }
+ else
+ {
+ /* Perform a logical right shift to place the signbit in the least
+ significant bit, then truncate the result to the desired mode
+ and mask just this bit. */
+ temp = expand_shift (RSHIFT_EXPR, imode, temp,
+ build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
+ temp = gen_lowpart (rmode, temp);
+ temp = expand_binop (rmode, and_optab, temp, const1_rtx,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ }
+
+ return temp;
+}
+
+/* Expand fork or exec calls. TARGET is the desired target of the
+ call. ARGLIST is the list of arguments of the call. FN is the
+ identificator of the actual function. IGNORE is nonzero if the
+ value is to be ignored. */
+
+static rtx
+expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
+{
+ tree id, decl;
+ tree call;
+
+ /* If we are not profiling, just call the function. */
+ if (!profile_arc_flag)
+ return NULL_RTX;
+
+ /* Otherwise call the wrapper. This should be equivalent for the rest of
+ compiler, so the code does not diverge, and the wrapper may run the
+ code necessary for keeping the profiling sane. */
+
+ switch (DECL_FUNCTION_CODE (fn))
+ {
+ case BUILT_IN_FORK:
+ id = get_identifier ("__gcov_fork");
+ break;
+
+ case BUILT_IN_EXECL:
+ id = get_identifier ("__gcov_execl");
+ break;
+
+ case BUILT_IN_EXECV:
+ id = get_identifier ("__gcov_execv");
+ break;
+
+ case BUILT_IN_EXECLP:
+ id = get_identifier ("__gcov_execlp");
+ break;
+
+ case BUILT_IN_EXECLE:
+ id = get_identifier ("__gcov_execle");
+ break;
+
+ case BUILT_IN_EXECVP:
+ id = get_identifier ("__gcov_execvp");
+ break;
+
+ case BUILT_IN_EXECVE:
+ id = get_identifier ("__gcov_execve");
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
+ DECL_EXTERNAL (decl) = 1;
+ TREE_PUBLIC (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ TREE_NOTHROW (decl) = 1;
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ call = build_function_call_expr (decl, arglist);
+
+ return expand_call (call, target, ignore);
+}
+
+
+/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
+ the pointer in these functions is void*, the tree optimizers may remove
+ casts. The mode computed in expand_builtin isn't reliable either, due
+ to __sync_bool_compare_and_swap.
+
+ FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
+ group of builtins. This gives us log2 of the mode size. */
+
+static inline enum machine_mode
+get_builtin_sync_mode (int fcode_diff)
+{
+ /* The size is not negotiable, so ask not to get BLKmode in return
+ if the target indicates that a smaller size would be better. */
+ return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
+}
+
+/* Expand the memory expression LOC and return the appropriate memory operand
+ for the builtin_sync operations. */
+
+static rtx
+get_builtin_sync_mem (tree loc, enum machine_mode mode)
+{
+ rtx addr, mem;
+
+ addr = expand_expr (loc, NULL, Pmode, EXPAND_SUM);
+
+ /* Note that we explicitly do not want any alias information for this
+ memory, so that we kill all other live memories. Otherwise we don't
+ satisfy the full barrier semantics of the intrinsic. */
+ mem = validize_mem (gen_rtx_MEM (mode, addr));
+
+ set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
+ set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
+ MEM_VOLATILE_P (mem) = 1;
+
+ return mem;
+}
+
+/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
+ ARGLIST is the operands list to the function. CODE is the rtx code
+ that corresponds to the arithmetic or logical operation from the name;
+ an exception here is that NOT actually means NAND. TARGET is an optional
+ place for us to store the results; AFTER is true if this is the
+ fetch_and_xxx form. IGNORE is true if we don't actually care about
+ the result of the operation at all. */
+
+static rtx
+expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
+ enum rtx_code code, bool after,
+ rtx target, bool ignore)
+{
+ rtx val, mem;
+ enum machine_mode old_mode;
+
+ /* Expand the operands. */
+ mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
+
+ arglist = TREE_CHAIN (arglist);
+ val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
+ /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
+ of CONST_INTs, where we know the old_mode only from the call argument. */
+ old_mode = GET_MODE (val);
+ if (old_mode == VOIDmode)
+ old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
+ val = convert_modes (mode, old_mode, val, 1);
+
+ if (ignore)
+ return expand_sync_operation (mem, val, code);
+ else
+ return expand_sync_fetch_operation (mem, val, code, after, target);
+}
+
+/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
+ intrinsics. ARGLIST is the operands list to the function. IS_BOOL is
+ true if this is the boolean form. TARGET is a place for us to store the
+ results; this is NOT optional if IS_BOOL is true. */
+
+static rtx
+expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
+ bool is_bool, rtx target)
+{
+ rtx old_val, new_val, mem;
+ enum machine_mode old_mode;
+
+ /* Expand the operands. */
+ mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
+
+ arglist = TREE_CHAIN (arglist);
+ old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
+ /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
+ of CONST_INTs, where we know the old_mode only from the call argument. */
+ old_mode = GET_MODE (old_val);
+ if (old_mode == VOIDmode)
+ old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
+ old_val = convert_modes (mode, old_mode, old_val, 1);
+
+ arglist = TREE_CHAIN (arglist);
+ new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
+ /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
+ of CONST_INTs, where we know the old_mode only from the call argument. */
+ old_mode = GET_MODE (new_val);
+ if (old_mode == VOIDmode)
+ old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
+ new_val = convert_modes (mode, old_mode, new_val, 1);
+
+ if (is_bool)
+ return expand_bool_compare_and_swap (mem, old_val, new_val, target);
+ else
+ return expand_val_compare_and_swap (mem, old_val, new_val, target);
+}
+
+/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
+ general form is actually an atomic exchange, and some targets only
+ support a reduced form with the second argument being a constant 1.
+ ARGLIST is the operands list to the function; TARGET is an optional
+ place for us to store the results. */
+
+static rtx
+expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
+ rtx target)
+{
+ rtx val, mem;
+ enum machine_mode old_mode;
+
+ /* Expand the operands. */
+ mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
+
+ arglist = TREE_CHAIN (arglist);
+ val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
+ /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
+ of CONST_INTs, where we know the old_mode only from the call argument. */
+ old_mode = GET_MODE (val);
+ if (old_mode == VOIDmode)
+ old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
+ val = convert_modes (mode, old_mode, val, 1);
+
+ return expand_sync_lock_test_and_set (mem, val, target);
+}
+
+/* Expand the __sync_synchronize intrinsic. */
+
+static void
+expand_builtin_synchronize (void)
+{
+ tree x;
+
+#ifdef HAVE_memory_barrier
+ if (HAVE_memory_barrier)
+ {
+ emit_insn (gen_memory_barrier ());
+ return;
+ }
+#endif
+
+ /* If no explicit memory barrier instruction is available, create an
+ empty asm stmt with a memory clobber. */
+ x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
+ tree_cons (NULL, build_string (6, "memory"), NULL));
+ ASM_VOLATILE_P (x) = 1;
+ expand_asm_expr (x);
+}
+
+/* Expand the __sync_lock_release intrinsic. ARGLIST is the operands list
+ to the function. */
+
+static void
+expand_builtin_lock_release (enum machine_mode mode, tree arglist)
+{
+ enum insn_code icode;
+ rtx mem, insn;
+ rtx val = const0_rtx;
+
+ /* Expand the operands. */
+ mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
+
+ /* If there is an explicit operation in the md file, use it. */
+ icode = sync_lock_release[mode];
+ if (icode != CODE_FOR_nothing)
+ {
+ if (!insn_data[icode].operand[1].predicate (val, mode))
+ val = force_reg (mode, val);
+
+ insn = GEN_FCN (icode) (mem, val);
+ if (insn)
+ {
+ emit_insn (insn);
+ return;
+ }
+ }
+
+ /* Otherwise we can implement this operation by emitting a barrier
+ followed by a store of zero. */
+ expand_builtin_synchronize ();
+ emit_move_insn (mem, val);
+}
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
@@ -4948,16 +5651,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
- /* Perform postincrements before expanding builtin functions. */
- emit_queue ();
-
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
- return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
+ return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
/* When not optimizing, generate calls to library functions for a certain
set of builtins. */
if (!optimize
- && !CALLED_AS_BUILT_IN (fndecl)
+ && !called_as_built_in (fndecl)
&& DECL_ASSEMBLER_NAME_SET_P (fndecl)
&& fcode != BUILT_IN_ALLOCA)
return expand_call (exp, target, ignore);
@@ -4994,103 +5694,81 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
switch (fcode)
{
- case BUILT_IN_ABS:
- case BUILT_IN_LABS:
- case BUILT_IN_LLABS:
- case BUILT_IN_IMAXABS:
- /* build_function_call changes these into ABS_EXPR. */
- abort ();
-
- case BUILT_IN_FABS:
- case BUILT_IN_FABSF:
- case BUILT_IN_FABSL:
+ CASE_FLT_FN (BUILT_IN_FABS):
target = expand_builtin_fabs (arglist, target, subtarget);
if (target)
- return target;
+ return target;
break;
- case BUILT_IN_CABS:
- case BUILT_IN_CABSF:
- case BUILT_IN_CABSL:
- if (flag_unsafe_math_optimizations)
- {
- target = expand_builtin_cabs (arglist, target);
- if (target)
- return target;
- }
+ CASE_FLT_FN (BUILT_IN_COPYSIGN):
+ target = expand_builtin_copysign (arglist, target, subtarget);
+ if (target)
+ return target;
break;
- case BUILT_IN_CONJ:
- case BUILT_IN_CONJF:
- case BUILT_IN_CONJL:
- case BUILT_IN_CREAL:
- case BUILT_IN_CREALF:
- case BUILT_IN_CREALL:
- case BUILT_IN_CIMAG:
- case BUILT_IN_CIMAGF:
- case BUILT_IN_CIMAGL:
- /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR
- and IMAGPART_EXPR. */
- abort ();
-
- case BUILT_IN_SIN:
- case BUILT_IN_SINF:
- case BUILT_IN_SINL:
- case BUILT_IN_COS:
- case BUILT_IN_COSF:
- case BUILT_IN_COSL:
- case BUILT_IN_EXP:
- case BUILT_IN_EXPF:
- case BUILT_IN_EXPL:
- case BUILT_IN_LOG:
- case BUILT_IN_LOGF:
- case BUILT_IN_LOGL:
- case BUILT_IN_TAN:
- case BUILT_IN_TANF:
- case BUILT_IN_TANL:
- case BUILT_IN_ATAN:
- case BUILT_IN_ATANF:
- case BUILT_IN_ATANL:
+ /* Just do a normal library call if we were unable to fold
+ the values. */
+ CASE_FLT_FN (BUILT_IN_CABS):
+ break;
+
+ CASE_FLT_FN (BUILT_IN_EXP):
+ CASE_FLT_FN (BUILT_IN_EXP10):
+ CASE_FLT_FN (BUILT_IN_POW10):
+ CASE_FLT_FN (BUILT_IN_EXP2):
+ CASE_FLT_FN (BUILT_IN_EXPM1):
+ CASE_FLT_FN (BUILT_IN_LOGB):
+ CASE_FLT_FN (BUILT_IN_ILOGB):
+ CASE_FLT_FN (BUILT_IN_LOG):
+ CASE_FLT_FN (BUILT_IN_LOG10):
+ CASE_FLT_FN (BUILT_IN_LOG2):
+ CASE_FLT_FN (BUILT_IN_LOG1P):
+ CASE_FLT_FN (BUILT_IN_TAN):
+ CASE_FLT_FN (BUILT_IN_ASIN):
+ CASE_FLT_FN (BUILT_IN_ACOS):
+ CASE_FLT_FN (BUILT_IN_ATAN):
/* Treat these like sqrt only if unsafe math optimizations are allowed,
because of possible accuracy problems. */
if (! flag_unsafe_math_optimizations)
break;
- case BUILT_IN_SQRT:
- case BUILT_IN_SQRTF:
- case BUILT_IN_SQRTL:
- case BUILT_IN_FLOOR:
- case BUILT_IN_FLOORF:
- case BUILT_IN_FLOORL:
- case BUILT_IN_CEIL:
- case BUILT_IN_CEILF:
- case BUILT_IN_CEILL:
- case BUILT_IN_TRUNC:
- case BUILT_IN_TRUNCF:
- case BUILT_IN_TRUNCL:
- case BUILT_IN_ROUND:
- case BUILT_IN_ROUNDF:
- case BUILT_IN_ROUNDL:
- case BUILT_IN_NEARBYINT:
- case BUILT_IN_NEARBYINTF:
- case BUILT_IN_NEARBYINTL:
+ CASE_FLT_FN (BUILT_IN_SQRT):
+ CASE_FLT_FN (BUILT_IN_FLOOR):
+ CASE_FLT_FN (BUILT_IN_CEIL):
+ CASE_FLT_FN (BUILT_IN_TRUNC):
+ CASE_FLT_FN (BUILT_IN_ROUND):
+ CASE_FLT_FN (BUILT_IN_NEARBYINT):
+ CASE_FLT_FN (BUILT_IN_RINT):
+ CASE_FLT_FN (BUILT_IN_LRINT):
+ CASE_FLT_FN (BUILT_IN_LLRINT):
target = expand_builtin_mathfn (exp, target, subtarget);
if (target)
return target;
break;
- case BUILT_IN_POW:
- case BUILT_IN_POWF:
- case BUILT_IN_POWL:
- if (! flag_unsafe_math_optimizations)
- break;
+ CASE_FLT_FN (BUILT_IN_LCEIL):
+ CASE_FLT_FN (BUILT_IN_LLCEIL):
+ CASE_FLT_FN (BUILT_IN_LFLOOR):
+ CASE_FLT_FN (BUILT_IN_LLFLOOR):
+ target = expand_builtin_int_roundingfn (exp, target, subtarget);
+ if (target)
+ return target;
+ break;
+
+ CASE_FLT_FN (BUILT_IN_POW):
target = expand_builtin_pow (exp, target, subtarget);
if (target)
return target;
break;
- case BUILT_IN_ATAN2:
- case BUILT_IN_ATAN2F:
- case BUILT_IN_ATAN2L:
+ CASE_FLT_FN (BUILT_IN_POWI):
+ target = expand_builtin_powi (exp, target, subtarget);
+ if (target)
+ return target;
+ break;
+
+ CASE_FLT_FN (BUILT_IN_ATAN2):
+ CASE_FLT_FN (BUILT_IN_LDEXP):
+ CASE_FLT_FN (BUILT_IN_FMOD):
+ CASE_FLT_FN (BUILT_IN_DREM):
if (! flag_unsafe_math_optimizations)
break;
target = expand_builtin_mathfn_2 (exp, target, subtarget);
@@ -5098,6 +5776,23 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target;
break;
+ CASE_FLT_FN (BUILT_IN_SIN):
+ CASE_FLT_FN (BUILT_IN_COS):
+ if (! flag_unsafe_math_optimizations)
+ break;
+ target = expand_builtin_mathfn_3 (exp, target, subtarget);
+ if (target)
+ return target;
+ break;
+
+ CASE_FLT_FN (BUILT_IN_SINCOS):
+ if (! flag_unsafe_math_optimizations)
+ break;
+ target = expand_builtin_sincos (exp);
+ if (target)
+ return target;
+ break;
+
case BUILT_IN_APPLY_ARGS:
return expand_builtin_apply_args ();
@@ -5124,7 +5819,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
rtx ops[3];
for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
- ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
+ ops[i] = expand_normal (TREE_VALUE (t));
return expand_builtin_apply (ops[0], ops[1], ops[2]);
}
@@ -5134,8 +5829,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
memory returned by __builtin_apply. */
case BUILT_IN_RETURN:
if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
- expand_builtin_return (expand_expr (TREE_VALUE (arglist),
- NULL_RTX, VOIDmode, 0));
+ expand_builtin_return (expand_normal (TREE_VALUE (arglist)));
return const0_rtx;
case BUILT_IN_SAVEREGS:
@@ -5146,13 +5840,15 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
/* Return the address of the first anonymous stack arg. */
case BUILT_IN_NEXT_ARG:
- return expand_builtin_next_arg (arglist);
+ if (fold_builtin_next_arg (arglist))
+ return const0_rtx;
+ return expand_builtin_next_arg ();
case BUILT_IN_CLASSIFY_TYPE:
return expand_builtin_classify_type (arglist);
case BUILT_IN_CONSTANT_P:
- return expand_builtin_constant_p (arglist, target_mode);
+ return const0_rtx;
case BUILT_IN_FRAME_ADDRESS:
case BUILT_IN_RETURN_ADDRESS:
@@ -5163,7 +5859,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
if (arglist != 0
|| ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
- || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
+ || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
return const0_rtx;
else
return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
@@ -5174,45 +5870,47 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target;
break;
- case BUILT_IN_FFS:
- case BUILT_IN_FFSL:
- case BUILT_IN_FFSLL:
+ case BUILT_IN_STACK_SAVE:
+ return expand_stack_save ();
+
+ case BUILT_IN_STACK_RESTORE:
+ expand_stack_restore (TREE_VALUE (arglist));
+ return const0_rtx;
+
+ CASE_INT_FN (BUILT_IN_FFS):
+ case BUILT_IN_FFSIMAX:
target = expand_builtin_unop (target_mode, arglist, target,
subtarget, ffs_optab);
if (target)
return target;
break;
- case BUILT_IN_CLZ:
- case BUILT_IN_CLZL:
- case BUILT_IN_CLZLL:
+ CASE_INT_FN (BUILT_IN_CLZ):
+ case BUILT_IN_CLZIMAX:
target = expand_builtin_unop (target_mode, arglist, target,
subtarget, clz_optab);
if (target)
return target;
break;
- case BUILT_IN_CTZ:
- case BUILT_IN_CTZL:
- case BUILT_IN_CTZLL:
+ CASE_INT_FN (BUILT_IN_CTZ):
+ case BUILT_IN_CTZIMAX:
target = expand_builtin_unop (target_mode, arglist, target,
subtarget, ctz_optab);
if (target)
return target;
break;
- case BUILT_IN_POPCOUNT:
- case BUILT_IN_POPCOUNTL:
- case BUILT_IN_POPCOUNTLL:
+ CASE_INT_FN (BUILT_IN_POPCOUNT):
+ case BUILT_IN_POPCOUNTIMAX:
target = expand_builtin_unop (target_mode, arglist, target,
subtarget, popcount_optab);
if (target)
return target;
break;
- case BUILT_IN_PARITY:
- case BUILT_IN_PARITYL:
- case BUILT_IN_PARITYLL:
+ CASE_INT_FN (BUILT_IN_PARITY):
+ case BUILT_IN_PARITYIMAX:
target = expand_builtin_unop (target_mode, arglist, target,
subtarget, parity_optab);
if (target)
@@ -5226,25 +5924,25 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
case BUILT_IN_STRCPY:
- target = expand_builtin_strcpy (arglist, target, mode);
+ target = expand_builtin_strcpy (fndecl, arglist, target, mode);
if (target)
return target;
break;
case BUILT_IN_STRNCPY:
- target = expand_builtin_strncpy (arglist, target, mode);
+ target = expand_builtin_strncpy (exp, target, mode);
if (target)
return target;
break;
case BUILT_IN_STPCPY:
- target = expand_builtin_stpcpy (arglist, target, mode);
+ target = expand_builtin_stpcpy (exp, target, mode);
if (target)
return target;
break;
case BUILT_IN_STRCAT:
- target = expand_builtin_strcat (arglist, target, mode);
+ target = expand_builtin_strcat (fndecl, arglist, target, mode);
if (target)
return target;
break;
@@ -5268,63 +5966,64 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
case BUILT_IN_STRSTR:
- target = expand_builtin_strstr (arglist, target, mode);
+ target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode);
if (target)
return target;
break;
case BUILT_IN_STRPBRK:
- target = expand_builtin_strpbrk (arglist, target, mode);
+ target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode);
if (target)
return target;
break;
case BUILT_IN_INDEX:
case BUILT_IN_STRCHR:
- target = expand_builtin_strchr (arglist, target, mode);
+ target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode);
if (target)
return target;
break;
case BUILT_IN_RINDEX:
case BUILT_IN_STRRCHR:
- target = expand_builtin_strrchr (arglist, target, mode);
+ target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode);
if (target)
return target;
break;
case BUILT_IN_MEMCPY:
- target = expand_builtin_memcpy (arglist, target, mode);
+ target = expand_builtin_memcpy (exp, target, mode);
if (target)
return target;
break;
case BUILT_IN_MEMPCPY:
- target = expand_builtin_mempcpy (arglist, target, mode, /*endp=*/ 1);
+ target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
if (target)
return target;
break;
case BUILT_IN_MEMMOVE:
- target = expand_builtin_memmove (arglist, target, mode);
+ target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target,
+ mode, exp);
if (target)
return target;
break;
case BUILT_IN_BCOPY:
- target = expand_builtin_bcopy (arglist);
+ target = expand_builtin_bcopy (exp);
if (target)
return target;
break;
case BUILT_IN_MEMSET:
- target = expand_builtin_memset (arglist, target, mode);
+ target = expand_builtin_memset (arglist, target, mode, exp);
if (target)
return target;
break;
case BUILT_IN_BZERO:
- target = expand_builtin_bzero (arglist);
+ target = expand_builtin_bzero (exp);
if (target)
return target;
break;
@@ -5349,46 +6048,110 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
case BUILT_IN_SETJMP:
- target = expand_builtin_setjmp (arglist, target);
- if (target)
- return target;
+ /* This should have been lowered to the builtins below. */
+ gcc_unreachable ();
+
+ case BUILT_IN_SETJMP_SETUP:
+ /* __builtin_setjmp_setup is passed a pointer to an array of five words
+ and the receiver label. */
+ if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ {
+ rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
+ VOIDmode, EXPAND_NORMAL);
+ tree label = TREE_OPERAND (TREE_VALUE (TREE_CHAIN (arglist)), 0);
+ rtx label_r = label_rtx (label);
+
+ /* This is copied from the handling of non-local gotos. */
+ expand_builtin_setjmp_setup (buf_addr, label_r);
+ nonlocal_goto_handler_labels
+ = gen_rtx_EXPR_LIST (VOIDmode, label_r,
+ nonlocal_goto_handler_labels);
+ /* ??? Do not let expand_label treat us as such since we would
+ not want to be both on the list of non-local labels and on
+ the list of forced labels. */
+ FORCED_LABEL (label) = 0;
+ return const0_rtx;
+ }
+ break;
+
+ case BUILT_IN_SETJMP_DISPATCHER:
+ /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
+ if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
+ {
+ tree label = TREE_OPERAND (TREE_VALUE (arglist), 0);
+ rtx label_r = label_rtx (label);
+
+ /* Remove the dispatcher label from the list of non-local labels
+ since the receiver labels have been added to it above. */
+ remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
+ return const0_rtx;
+ }
+ break;
+
+ case BUILT_IN_SETJMP_RECEIVER:
+ /* __builtin_setjmp_receiver is passed the receiver label. */
+ if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
+ {
+ tree label = TREE_OPERAND (TREE_VALUE (arglist), 0);
+ rtx label_r = label_rtx (label);
+
+ expand_builtin_setjmp_receiver (label_r);
+ return const0_rtx;
+ }
break;
/* __builtin_longjmp is passed a pointer to an array of five words.
It's similar to the C library longjmp function but works with
__builtin_setjmp above. */
case BUILT_IN_LONGJMP:
- if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
- break;
- else
+ if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
- VOIDmode, 0);
- rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
- NULL_RTX, VOIDmode, 0);
+ VOIDmode, EXPAND_NORMAL);
+ rtx value = expand_normal (TREE_VALUE (TREE_CHAIN (arglist)));
if (value != const1_rtx)
{
- error ("__builtin_longjmp second argument must be 1");
+ error ("%<__builtin_longjmp%> second argument must be 1");
return const0_rtx;
}
expand_builtin_longjmp (buf_addr, value);
return const0_rtx;
}
+ break;
+
+ case BUILT_IN_NONLOCAL_GOTO:
+ target = expand_builtin_nonlocal_goto (arglist);
+ if (target)
+ return target;
+ break;
+
+ /* This updates the setjmp buffer that is its argument with the value
+ of the current stack pointer. */
+ case BUILT_IN_UPDATE_SETJMP_BUF:
+ if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
+ {
+ rtx buf_addr
+ = expand_normal (TREE_VALUE (arglist));
+
+ expand_builtin_update_setjmp_buf (buf_addr);
+ return const0_rtx;
+ }
+ break;
case BUILT_IN_TRAP:
expand_builtin_trap ();
return const0_rtx;
case BUILT_IN_PRINTF:
- target = expand_builtin_printf (arglist, target, mode, false);
+ target = expand_builtin_printf (exp, target, mode, false);
if (target)
return target;
break;
case BUILT_IN_PRINTF_UNLOCKED:
- target = expand_builtin_printf (arglist, target, mode, true);
+ target = expand_builtin_printf (exp, target, mode, true);
if (target)
return target;
break;
@@ -5398,7 +6161,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
if (target)
return target;
break;
-
case BUILT_IN_FPUTS_UNLOCKED:
target = expand_builtin_fputs (arglist, target, true);
if (target)
@@ -5406,13 +6168,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
case BUILT_IN_FPRINTF:
- target = expand_builtin_fprintf (arglist, target, mode, false);
+ target = expand_builtin_fprintf (exp, target, mode, false);
if (target)
return target;
break;
case BUILT_IN_FPRINTF_UNLOCKED:
- target = expand_builtin_fprintf (arglist, target, mode, true);
+ target = expand_builtin_fprintf (exp, target, mode, true);
if (target)
return target;
break;
@@ -5423,6 +6185,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target;
break;
+ CASE_FLT_FN (BUILT_IN_SIGNBIT):
+ target = expand_builtin_signbit (exp, target);
+ if (target)
+ return target;
+ break;
+
/* Various hooks for the DWARF 2 __throw routine. */
case BUILT_IN_UNWIND_INIT:
expand_builtin_unwind_init ();
@@ -5464,11 +6232,251 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
expand_builtin_prefetch (arglist);
return const0_rtx;
+ case BUILT_IN_PROFILE_FUNC_ENTER:
+ return expand_builtin_profile_func (false);
+ case BUILT_IN_PROFILE_FUNC_EXIT:
+ return expand_builtin_profile_func (true);
+
+ case BUILT_IN_INIT_TRAMPOLINE:
+ return expand_builtin_init_trampoline (arglist);
+ case BUILT_IN_ADJUST_TRAMPOLINE:
+ return expand_builtin_adjust_trampoline (arglist);
+
+ case BUILT_IN_FORK:
+ case BUILT_IN_EXECL:
+ case BUILT_IN_EXECV:
+ case BUILT_IN_EXECLP:
+ case BUILT_IN_EXECLE:
+ case BUILT_IN_EXECVP:
+ case BUILT_IN_EXECVE:
+ target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_FETCH_AND_ADD_1:
+ case BUILT_IN_FETCH_AND_ADD_2:
+ case BUILT_IN_FETCH_AND_ADD_4:
+ case BUILT_IN_FETCH_AND_ADD_8:
+ case BUILT_IN_FETCH_AND_ADD_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
+ target = expand_builtin_sync_operation (mode, arglist, PLUS,
+ false, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_FETCH_AND_SUB_1:
+ case BUILT_IN_FETCH_AND_SUB_2:
+ case BUILT_IN_FETCH_AND_SUB_4:
+ case BUILT_IN_FETCH_AND_SUB_8:
+ case BUILT_IN_FETCH_AND_SUB_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
+ target = expand_builtin_sync_operation (mode, arglist, MINUS,
+ false, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_FETCH_AND_OR_1:
+ case BUILT_IN_FETCH_AND_OR_2:
+ case BUILT_IN_FETCH_AND_OR_4:
+ case BUILT_IN_FETCH_AND_OR_8:
+ case BUILT_IN_FETCH_AND_OR_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
+ target = expand_builtin_sync_operation (mode, arglist, IOR,
+ false, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_FETCH_AND_AND_1:
+ case BUILT_IN_FETCH_AND_AND_2:
+ case BUILT_IN_FETCH_AND_AND_4:
+ case BUILT_IN_FETCH_AND_AND_8:
+ case BUILT_IN_FETCH_AND_AND_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
+ target = expand_builtin_sync_operation (mode, arglist, AND,
+ false, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_FETCH_AND_XOR_1:
+ case BUILT_IN_FETCH_AND_XOR_2:
+ case BUILT_IN_FETCH_AND_XOR_4:
+ case BUILT_IN_FETCH_AND_XOR_8:
+ case BUILT_IN_FETCH_AND_XOR_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
+ target = expand_builtin_sync_operation (mode, arglist, XOR,
+ false, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_FETCH_AND_NAND_1:
+ case BUILT_IN_FETCH_AND_NAND_2:
+ case BUILT_IN_FETCH_AND_NAND_4:
+ case BUILT_IN_FETCH_AND_NAND_8:
+ case BUILT_IN_FETCH_AND_NAND_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
+ target = expand_builtin_sync_operation (mode, arglist, NOT,
+ false, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_ADD_AND_FETCH_1:
+ case BUILT_IN_ADD_AND_FETCH_2:
+ case BUILT_IN_ADD_AND_FETCH_4:
+ case BUILT_IN_ADD_AND_FETCH_8:
+ case BUILT_IN_ADD_AND_FETCH_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
+ target = expand_builtin_sync_operation (mode, arglist, PLUS,
+ true, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_SUB_AND_FETCH_1:
+ case BUILT_IN_SUB_AND_FETCH_2:
+ case BUILT_IN_SUB_AND_FETCH_4:
+ case BUILT_IN_SUB_AND_FETCH_8:
+ case BUILT_IN_SUB_AND_FETCH_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
+ target = expand_builtin_sync_operation (mode, arglist, MINUS,
+ true, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_OR_AND_FETCH_1:
+ case BUILT_IN_OR_AND_FETCH_2:
+ case BUILT_IN_OR_AND_FETCH_4:
+ case BUILT_IN_OR_AND_FETCH_8:
+ case BUILT_IN_OR_AND_FETCH_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
+ target = expand_builtin_sync_operation (mode, arglist, IOR,
+ true, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_AND_AND_FETCH_1:
+ case BUILT_IN_AND_AND_FETCH_2:
+ case BUILT_IN_AND_AND_FETCH_4:
+ case BUILT_IN_AND_AND_FETCH_8:
+ case BUILT_IN_AND_AND_FETCH_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
+ target = expand_builtin_sync_operation (mode, arglist, AND,
+ true, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_XOR_AND_FETCH_1:
+ case BUILT_IN_XOR_AND_FETCH_2:
+ case BUILT_IN_XOR_AND_FETCH_4:
+ case BUILT_IN_XOR_AND_FETCH_8:
+ case BUILT_IN_XOR_AND_FETCH_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
+ target = expand_builtin_sync_operation (mode, arglist, XOR,
+ true, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_NAND_AND_FETCH_1:
+ case BUILT_IN_NAND_AND_FETCH_2:
+ case BUILT_IN_NAND_AND_FETCH_4:
+ case BUILT_IN_NAND_AND_FETCH_8:
+ case BUILT_IN_NAND_AND_FETCH_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
+ target = expand_builtin_sync_operation (mode, arglist, NOT,
+ true, target, ignore);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
+ case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
+ case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
+ case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
+ case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
+ if (mode == VOIDmode)
+ mode = TYPE_MODE (boolean_type_node);
+ if (!target || !register_operand (target, mode))
+ target = gen_reg_rtx (mode);
+
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
+ target = expand_builtin_compare_and_swap (mode, arglist, true, target);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
+ case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
+ case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
+ case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
+ case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
+ target = expand_builtin_compare_and_swap (mode, arglist, false, target);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_LOCK_TEST_AND_SET_1:
+ case BUILT_IN_LOCK_TEST_AND_SET_2:
+ case BUILT_IN_LOCK_TEST_AND_SET_4:
+ case BUILT_IN_LOCK_TEST_AND_SET_8:
+ case BUILT_IN_LOCK_TEST_AND_SET_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
+ target = expand_builtin_lock_test_and_set (mode, arglist, target);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_LOCK_RELEASE_1:
+ case BUILT_IN_LOCK_RELEASE_2:
+ case BUILT_IN_LOCK_RELEASE_4:
+ case BUILT_IN_LOCK_RELEASE_8:
+ case BUILT_IN_LOCK_RELEASE_16:
+ mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
+ expand_builtin_lock_release (mode, arglist);
+ return const0_rtx;
+
+ case BUILT_IN_SYNCHRONIZE:
+ expand_builtin_synchronize ();
+ return const0_rtx;
+
+ case BUILT_IN_OBJECT_SIZE:
+ return expand_builtin_object_size (exp);
+
+ case BUILT_IN_MEMCPY_CHK:
+ case BUILT_IN_MEMPCPY_CHK:
+ case BUILT_IN_MEMMOVE_CHK:
+ case BUILT_IN_MEMSET_CHK:
+ target = expand_builtin_memory_chk (exp, target, mode, fcode);
+ if (target)
+ return target;
+ break;
+
+ case BUILT_IN_STRCPY_CHK:
+ case BUILT_IN_STPCPY_CHK:
+ case BUILT_IN_STRNCPY_CHK:
+ case BUILT_IN_STRCAT_CHK:
+ case BUILT_IN_SNPRINTF_CHK:
+ case BUILT_IN_VSNPRINTF_CHK:
+ maybe_emit_chk_warning (exp, fcode);
+ break;
+
+ case BUILT_IN_SPRINTF_CHK:
+ case BUILT_IN_VSPRINTF_CHK:
+ maybe_emit_sprintf_chk_warning (exp, fcode);
+ break;
default: /* just do library call, if unknown builtin */
- if (!DECL_ASSEMBLER_NAME_SET_P (fndecl))
- error ("built-in function `%s' not currently supported",
- IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ break;
}
/* The switch statement above can drop through to cause the function
@@ -5565,12 +6573,19 @@ fold_builtin_constant_p (tree arglist)
STRIP_NOPS (arglist);
/* If we know this is a constant, emit the constant of one. */
- if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
+ if (CONSTANT_CLASS_P (arglist)
|| (TREE_CODE (arglist) == CONSTRUCTOR
- && TREE_CONSTANT (arglist))
- || (TREE_CODE (arglist) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
+ && TREE_CONSTANT (arglist)))
return integer_one_node;
+ if (TREE_CODE (arglist) == ADDR_EXPR)
+ {
+ tree op = TREE_OPERAND (arglist, 0);
+ if (TREE_CODE (op) == STRING_CST
+ || (TREE_CODE (op) == ARRAY_REF
+ && integer_zerop (TREE_OPERAND (op, 1))
+ && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
+ return integer_one_node;
+ }
/* If this expression has side effects, show we don't know it to be a
constant. Likewise if it's a pointer or aggregate type since in
@@ -5582,21 +6597,84 @@ fold_builtin_constant_p (tree arglist)
if (TREE_SIDE_EFFECTS (arglist)
|| AGGREGATE_TYPE_P (TREE_TYPE (arglist))
|| POINTER_TYPE_P (TREE_TYPE (arglist))
- || cfun == 0)
+ || cfun == 0
+ || folding_initializer)
return integer_zero_node;
return 0;
}
+/* Fold a call to __builtin_expect, if we expect that a comparison against
+ the argument will fold to a constant. In practice, this means a true
+ constant or the address of a non-weak symbol. ARGLIST is the argument
+ list of the call. */
+
+static tree
+fold_builtin_expect (tree arglist)
+{
+ tree arg, inner;
+
+ if (arglist == 0)
+ return 0;
+
+ arg = TREE_VALUE (arglist);
+
+ /* If the argument isn't invariant, then there's nothing we can do. */
+ if (!TREE_INVARIANT (arg))
+ return 0;
+
+ /* If we're looking at an address of a weak decl, then do not fold. */
+ inner = arg;
+ STRIP_NOPS (inner);
+ if (TREE_CODE (inner) == ADDR_EXPR)
+ {
+ do
+ {
+ inner = TREE_OPERAND (inner, 0);
+ }
+ while (TREE_CODE (inner) == COMPONENT_REF
+ || TREE_CODE (inner) == ARRAY_REF);
+ if (DECL_P (inner) && DECL_WEAK (inner))
+ return 0;
+ }
+
+ /* Otherwise, ARG already has the proper type for the return value. */
+ return arg;
+}
+
/* Fold a call to __builtin_classify_type. */
static tree
fold_builtin_classify_type (tree arglist)
{
if (arglist == 0)
- return build_int_2 (no_type_class, 0);
+ return build_int_cst (NULL_TREE, no_type_class);
- return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
+ return build_int_cst (NULL_TREE,
+ type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
+}
+
+/* Fold a call to __builtin_strlen. */
+
+static tree
+fold_builtin_strlen (tree arglist)
+{
+ if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
+ return NULL_TREE;
+ else
+ {
+ tree len = c_strlen (TREE_VALUE (arglist), 0);
+
+ if (len)
+ {
+ /* Convert from the internal "sizetype" type to "size_t". */
+ if (size_type_node)
+ len = fold_convert (size_type_node, len);
+ return len;
+ }
+
+ return NULL_TREE;
+ }
}
/* Fold a call to __builtin_inf or __builtin_huge_val. */
@@ -5606,8 +6684,15 @@ fold_builtin_inf (tree type, int warn)
{
REAL_VALUE_TYPE real;
+ /* __builtin_inff is intended to be usable to define INFINITY on all
+ targets. If an infinity is not available, INFINITY expands "to a
+ positive constant of type float that overflows at translation
+ time", footnote "In this case, using INFINITY will violate the
+ constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
+ Thus we pedwarn to ensure this constraint violation is
+ diagnosed. */
if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
- warning ("target format does not support infinity");
+ pedwarn ("target format does not support infinity");
real_inf (&real);
return build_real (type, real);
@@ -5669,12 +6754,13 @@ integer_valued_real_p (tree t)
case REAL_CST:
if (! TREE_CONSTANT_OVERFLOW (t))
{
- REAL_VALUE_TYPE c, cint;
+ REAL_VALUE_TYPE c, cint;
c = TREE_REAL_CST (t);
real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
return real_identical (&c, &cint);
}
+ break;
case NOP_EXPR:
{
@@ -5689,21 +6775,12 @@ integer_valued_real_p (tree t)
case CALL_EXPR:
switch (builtin_mathfn_code (t))
{
- case BUILT_IN_CEIL:
- case BUILT_IN_CEILF:
- case BUILT_IN_CEILL:
- case BUILT_IN_FLOOR:
- case BUILT_IN_FLOORF:
- case BUILT_IN_FLOORL:
- case BUILT_IN_NEARBYINT:
- case BUILT_IN_NEARBYINTF:
- case BUILT_IN_NEARBYINTL:
- case BUILT_IN_ROUND:
- case BUILT_IN_ROUNDF:
- case BUILT_IN_ROUNDL:
- case BUILT_IN_TRUNC:
- case BUILT_IN_TRUNCF:
- case BUILT_IN_TRUNCL:
+ CASE_FLT_FN (BUILT_IN_CEIL):
+ CASE_FLT_FN (BUILT_IN_FLOOR):
+ CASE_FLT_FN (BUILT_IN_NEARBYINT):
+ CASE_FLT_FN (BUILT_IN_RINT):
+ CASE_FLT_FN (BUILT_IN_ROUND):
+ CASE_FLT_FN (BUILT_IN_TRUNC):
return true;
default:
@@ -5722,10 +6799,8 @@ integer_valued_real_p (tree t)
Do the transformation. */
static tree
-fold_trunc_transparent_mathfn (tree exp)
+fold_trunc_transparent_mathfn (tree fndecl, tree arglist)
{
- tree fndecl = get_callee_fndecl (exp);
- tree arglist = TREE_OPERAND (exp, 1);
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
tree arg;
@@ -5745,7 +6820,45 @@ fold_trunc_transparent_mathfn (tree exp)
if (optimize)
{
tree arg0 = strip_float_extensions (arg);
- tree ftype = TREE_TYPE (exp);
+ tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
+ tree newtype = TREE_TYPE (arg0);
+ tree decl;
+
+ if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
+ && (decl = mathfn_built_in (newtype, fcode)))
+ {
+ arglist =
+ build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
+ return fold_convert (ftype,
+ build_function_call_expr (decl, arglist));
+ }
+ }
+ return 0;
+}
+
+/* EXP is assumed to be builtin call which can narrow the FP type of
+ the argument, for instance lround((double)f) -> lroundf (f). */
+
+static tree
+fold_fixed_mathfn (tree fndecl, tree arglist)
+{
+ enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+ tree arg;
+
+ if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return 0;
+
+ arg = TREE_VALUE (arglist);
+
+ /* If argument is already integer valued, and we don't need to worry
+ about setting errno, there's no need to perform rounding. */
+ if (! flag_errno_math && integer_valued_real_p (arg))
+ return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
+
+ if (optimize)
+ {
+ tree ftype = TREE_TYPE (arg);
+ tree arg0 = strip_float_extensions (arg);
tree newtype = TREE_TYPE (arg0);
tree decl;
@@ -5753,20 +6866,56 @@ fold_trunc_transparent_mathfn (tree exp)
&& (decl = mathfn_built_in (newtype, fcode)))
{
arglist =
- build_tree_list (NULL_TREE, fold (convert (newtype, arg0)));
- return convert (ftype,
- build_function_call_expr (decl, arglist));
+ build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
+ return build_function_call_expr (decl, arglist);
+ }
+ }
+
+ /* Canonicalize llround (x) to lround (x) on LP64 targets where
+ sizeof (long long) == sizeof (long). */
+ if (TYPE_PRECISION (long_long_integer_type_node)
+ == TYPE_PRECISION (long_integer_type_node))
+ {
+ tree newfn = NULL_TREE;
+ switch (fcode)
+ {
+ CASE_FLT_FN (BUILT_IN_LLCEIL):
+ newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_LLFLOOR):
+ newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_LLROUND):
+ newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_LLRINT):
+ newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
+ break;
+
+ default:
+ break;
+ }
+
+ if (newfn)
+ {
+ tree newcall = build_function_call_expr (newfn, arglist);
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
}
}
+
return 0;
}
-/* Fold function call to builtin cabs, cabsf or cabsl. FNDECL is the
- function's DECL, ARGLIST is the argument list and TYPE is the return
- type. Return NULL_TREE if no simplification can be made. */
+/* Fold function call to builtin cabs, cabsf or cabsl. ARGLIST
+ is the argument list, TYPE is the return type and FNDECL is the
+ original function DECL. Return NULL_TREE if no if no simplification
+ can be made. */
static tree
-fold_builtin_cabs (tree fndecl, tree arglist, tree type)
+fold_builtin_cabs (tree arglist, tree type, tree fndecl)
{
tree arg;
@@ -5802,43 +6951,42 @@ fold_builtin_cabs (tree fndecl, tree arglist, tree type)
/* If either part is zero, cabs is fabs of the other. */
if (TREE_CODE (arg) == COMPLEX_EXPR
&& real_zerop (TREE_OPERAND (arg, 0)))
- return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1)));
+ return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1));
if (TREE_CODE (arg) == COMPLEX_EXPR
&& real_zerop (TREE_OPERAND (arg, 1)))
- return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0)));
+ return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
- if (flag_unsafe_math_optimizations)
+ /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
+ if (TREE_CODE (arg) == NEGATE_EXPR
+ || TREE_CODE (arg) == CONJ_EXPR)
{
- enum built_in_function fcode;
- tree sqrtfn;
+ tree arglist = build_tree_list (NULL_TREE, TREE_OPERAND (arg, 0));
+ return build_function_call_expr (fndecl, arglist);
+ }
- fcode = DECL_FUNCTION_CODE (fndecl);
- if (fcode == BUILT_IN_CABS)
- sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
- else if (fcode == BUILT_IN_CABSF)
- sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
- else if (fcode == BUILT_IN_CABSL)
- sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
- else
- sqrtfn = NULL_TREE;
+ /* Don't do this when optimizing for size. */
+ if (flag_unsafe_math_optimizations
+ && optimize && !optimize_size)
+ {
+ tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
if (sqrtfn != NULL_TREE)
{
tree rpart, ipart, result, arglist;
- arg = save_expr (arg);
+ arg = builtin_save_expr (arg);
- rpart = fold (build1 (REALPART_EXPR, type, arg));
- ipart = fold (build1 (IMAGPART_EXPR, type, arg));
+ rpart = fold_build1 (REALPART_EXPR, type, arg);
+ ipart = fold_build1 (IMAGPART_EXPR, type, arg);
- rpart = save_expr (rpart);
- ipart = save_expr (ipart);
+ rpart = builtin_save_expr (rpart);
+ ipart = builtin_save_expr (ipart);
- result = fold (build (PLUS_EXPR, type,
- fold (build (MULT_EXPR, type,
- rpart, rpart)),
- fold (build (MULT_EXPR, type,
- ipart, ipart))));
+ result = fold_build2 (PLUS_EXPR, type,
+ fold_build2 (MULT_EXPR, type,
+ rpart, rpart),
+ fold_build2 (MULT_EXPR, type,
+ ipart, ipart));
arglist = build_tree_list (NULL_TREE, result);
return build_function_call_expr (sqrtfn, arglist);
@@ -5848,13 +6996,286 @@ fold_builtin_cabs (tree fndecl, tree arglist, tree type)
return NULL_TREE;
}
+/* Fold a builtin function call to sqrt, sqrtf, or sqrtl. Return
+ NULL_TREE if no simplification can be made. */
+
+static tree
+fold_builtin_sqrt (tree arglist, tree type)
+{
+
+ enum built_in_function fcode;
+ tree arg = TREE_VALUE (arglist);
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ /* Optimize sqrt of constant value. */
+ if (TREE_CODE (arg) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg))
+ {
+ REAL_VALUE_TYPE r, x;
+
+ x = TREE_REAL_CST (arg);
+ if (real_sqrt (&r, TYPE_MODE (type), &x)
+ || (!flag_trapping_math && !flag_errno_math))
+ return build_real (type, r);
+ }
+
+ /* Optimize sqrt(expN(x)) = expN(x*0.5). */
+ fcode = builtin_mathfn_code (arg);
+ if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
+ {
+ tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
+ arg = fold_build2 (MULT_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg, 1)),
+ build_real (type, dconsthalf));
+ arglist = build_tree_list (NULL_TREE, arg);
+ return build_function_call_expr (expfn, arglist);
+ }
+
+ /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
+ if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
+ {
+ tree powfn = mathfn_built_in (type, BUILT_IN_POW);
+
+ if (powfn)
+ {
+ tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
+ tree tree_root;
+ /* The inner root was either sqrt or cbrt. */
+ REAL_VALUE_TYPE dconstroot =
+ BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
+
+ /* Adjust for the outer root. */
+ SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
+ dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
+ tree_root = build_real (type, dconstroot);
+ arglist = tree_cons (NULL_TREE, arg0,
+ build_tree_list (NULL_TREE, tree_root));
+ return build_function_call_expr (powfn, arglist);
+ }
+ }
+
+ /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
+ if (flag_unsafe_math_optimizations
+ && (fcode == BUILT_IN_POW
+ || fcode == BUILT_IN_POWF
+ || fcode == BUILT_IN_POWL))
+ {
+ tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
+ tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
+ tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
+ tree narg1;
+ if (!tree_expr_nonnegative_p (arg0))
+ arg0 = build1 (ABS_EXPR, type, arg0);
+ narg1 = fold_build2 (MULT_EXPR, type, arg1,
+ build_real (type, dconsthalf));
+ arglist = tree_cons (NULL_TREE, arg0,
+ build_tree_list (NULL_TREE, narg1));
+ return build_function_call_expr (powfn, arglist);
+ }
+
+ return NULL_TREE;
+}
+
+/* Fold a builtin function call to cbrt, cbrtf, or cbrtl. Return
+ NULL_TREE if no simplification can be made. */
+static tree
+fold_builtin_cbrt (tree arglist, tree type)
+{
+ tree arg = TREE_VALUE (arglist);
+ const enum built_in_function fcode = builtin_mathfn_code (arg);
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ /* Optimize cbrt of constant value. */
+ if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
+ return arg;
+
+ if (flag_unsafe_math_optimizations)
+ {
+ /* Optimize cbrt(expN(x)) -> expN(x/3). */
+ if (BUILTIN_EXPONENT_P (fcode))
+ {
+ tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
+ const REAL_VALUE_TYPE third_trunc =
+ real_value_truncate (TYPE_MODE (type), dconstthird);
+ arg = fold_build2 (MULT_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (arg, 1)),
+ build_real (type, third_trunc));
+ arglist = build_tree_list (NULL_TREE, arg);
+ return build_function_call_expr (expfn, arglist);
+ }
+
+ /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
+ if (BUILTIN_SQRT_P (fcode))
+ {
+ tree powfn = mathfn_built_in (type, BUILT_IN_POW);
+
+ if (powfn)
+ {
+ tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
+ tree tree_root;
+ REAL_VALUE_TYPE dconstroot = dconstthird;
+
+ SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
+ dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
+ tree_root = build_real (type, dconstroot);
+ arglist = tree_cons (NULL_TREE, arg0,
+ build_tree_list (NULL_TREE, tree_root));
+ return build_function_call_expr (powfn, arglist);
+ }
+ }
+
+ /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
+ if (BUILTIN_CBRT_P (fcode))
+ {
+ tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
+ if (tree_expr_nonnegative_p (arg0))
+ {
+ tree powfn = mathfn_built_in (type, BUILT_IN_POW);
+
+ if (powfn)
+ {
+ tree tree_root;
+ REAL_VALUE_TYPE dconstroot;
+
+ real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
+ dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
+ tree_root = build_real (type, dconstroot);
+ arglist = tree_cons (NULL_TREE, arg0,
+ build_tree_list (NULL_TREE, tree_root));
+ return build_function_call_expr (powfn, arglist);
+ }
+ }
+ }
+
+ /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
+ if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
+ || fcode == BUILT_IN_POWL)
+ {
+ tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1));
+ tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
+ if (tree_expr_nonnegative_p (arg00))
+ {
+ tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
+ const REAL_VALUE_TYPE dconstroot
+ = real_value_truncate (TYPE_MODE (type), dconstthird);
+ tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
+ build_real (type, dconstroot));
+ arglist = tree_cons (NULL_TREE, arg00,
+ build_tree_list (NULL_TREE, narg01));
+ return build_function_call_expr (powfn, arglist);
+ }
+ }
+ }
+ return NULL_TREE;
+}
+
+/* Fold function call to builtin sin, sinf, or sinl. Return
+ NULL_TREE if no simplification can be made. */
+static tree
+fold_builtin_sin (tree arglist)
+{
+ tree arg = TREE_VALUE (arglist);
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ /* Optimize sin (0.0) = 0.0. */
+ if (real_zerop (arg))
+ return arg;
+
+ return NULL_TREE;
+}
+
+/* Fold function call to builtin cos, cosf, or cosl. Return
+ NULL_TREE if no simplification can be made. */
+static tree
+fold_builtin_cos (tree arglist, tree type, tree fndecl)
+{
+ tree arg = TREE_VALUE (arglist);
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ /* Optimize cos (0.0) = 1.0. */
+ if (real_zerop (arg))
+ return build_real (type, dconst1);
+
+ /* Optimize cos(-x) into cos (x). */
+ if (TREE_CODE (arg) == NEGATE_EXPR)
+ {
+ tree args = build_tree_list (NULL_TREE,
+ TREE_OPERAND (arg, 0));
+ return build_function_call_expr (fndecl, args);
+ }
+
+ return NULL_TREE;
+}
+
+/* Fold function call to builtin tan, tanf, or tanl. Return
+ NULL_TREE if no simplification can be made. */
+static tree
+fold_builtin_tan (tree arglist)
+{
+ enum built_in_function fcode;
+ tree arg = TREE_VALUE (arglist);
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ /* Optimize tan(0.0) = 0.0. */
+ if (real_zerop (arg))
+ return arg;
+
+ /* Optimize tan(atan(x)) = x. */
+ fcode = builtin_mathfn_code (arg);
+ if (flag_unsafe_math_optimizations
+ && (fcode == BUILT_IN_ATAN
+ || fcode == BUILT_IN_ATANF
+ || fcode == BUILT_IN_ATANL))
+ return TREE_VALUE (TREE_OPERAND (arg, 1));
+
+ return NULL_TREE;
+}
+
+/* Fold function call to builtin atan, atanf, or atanl. Return
+ NULL_TREE if no simplification can be made. */
+
+static tree
+fold_builtin_atan (tree arglist, tree type)
+{
+
+ tree arg = TREE_VALUE (arglist);
+
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ /* Optimize atan(0.0) = 0.0. */
+ if (real_zerop (arg))
+ return arg;
+
+ /* Optimize atan(1.0) = pi/4. */
+ if (real_onep (arg))
+ {
+ REAL_VALUE_TYPE cst;
+
+ real_convert (&cst, TYPE_MODE (type), &dconstpi);
+ SET_REAL_EXP (&cst, REAL_EXP (&cst) - 2);
+ return build_real (type, cst);
+ }
+
+ return NULL_TREE;
+}
+
/* Fold function call to builtin trunc, truncf or truncl. Return
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_trunc (tree exp)
+fold_builtin_trunc (tree fndecl, tree arglist)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree arg;
if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
@@ -5865,23 +7286,22 @@ fold_builtin_trunc (tree exp)
if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
{
REAL_VALUE_TYPE r, x;
- tree type = TREE_TYPE (exp);
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
x = TREE_REAL_CST (arg);
real_trunc (&r, TYPE_MODE (type), &x);
return build_real (type, r);
}
- return fold_trunc_transparent_mathfn (exp);
+ return fold_trunc_transparent_mathfn (fndecl, arglist);
}
/* Fold function call to builtin floor, floorf or floorl. Return
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_floor (tree exp)
+fold_builtin_floor (tree fndecl, tree arglist)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree arg;
if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
@@ -5896,7 +7316,7 @@ fold_builtin_floor (tree exp)
x = TREE_REAL_CST (arg);
if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
{
- tree type = TREE_TYPE (exp);
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
REAL_VALUE_TYPE r;
real_floor (&r, TYPE_MODE (type), &x);
@@ -5904,16 +7324,15 @@ fold_builtin_floor (tree exp)
}
}
- return fold_trunc_transparent_mathfn (exp);
+ return fold_trunc_transparent_mathfn (fndecl, arglist);
}
/* Fold function call to builtin ceil, ceilf or ceill. Return
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_ceil (tree exp)
+fold_builtin_ceil (tree fndecl, tree arglist)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree arg;
if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
@@ -5928,7 +7347,7 @@ fold_builtin_ceil (tree exp)
x = TREE_REAL_CST (arg);
if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
{
- tree type = TREE_TYPE (exp);
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
REAL_VALUE_TYPE r;
real_ceil (&r, TYPE_MODE (type), &x);
@@ -5936,7 +7355,94 @@ fold_builtin_ceil (tree exp)
}
}
- return fold_trunc_transparent_mathfn (exp);
+ return fold_trunc_transparent_mathfn (fndecl, arglist);
+}
+
+/* Fold function call to builtin round, roundf or roundl. Return
+ NULL_TREE if no simplification can be made. */
+
+static tree
+fold_builtin_round (tree fndecl, tree arglist)
+{
+ tree arg;
+
+ if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return 0;
+
+ /* Optimize round of constant value. */
+ arg = TREE_VALUE (arglist);
+ if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
+ {
+ REAL_VALUE_TYPE x;
+
+ x = TREE_REAL_CST (arg);
+ if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
+ {
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ REAL_VALUE_TYPE r;
+
+ real_round (&r, TYPE_MODE (type), &x);
+ return build_real (type, r);
+ }
+ }
+
+ return fold_trunc_transparent_mathfn (fndecl, arglist);
+}
+
+/* Fold function call to builtin lround, lroundf or lroundl (or the
+ corresponding long long versions) and other rounding functions.
+ Return NULL_TREE if no simplification can be made. */
+
+static tree
+fold_builtin_int_roundingfn (tree fndecl, tree arglist)
+{
+ tree arg;
+
+ if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return 0;
+
+ /* Optimize lround of constant value. */
+ arg = TREE_VALUE (arglist);
+ if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
+ {
+ const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
+
+ if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
+ {
+ tree itype = TREE_TYPE (TREE_TYPE (fndecl));
+ tree ftype = TREE_TYPE (arg), result;
+ HOST_WIDE_INT hi, lo;
+ REAL_VALUE_TYPE r;
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_LFLOOR):
+ CASE_FLT_FN (BUILT_IN_LLFLOOR):
+ real_floor (&r, TYPE_MODE (ftype), &x);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_LCEIL):
+ CASE_FLT_FN (BUILT_IN_LLCEIL):
+ real_ceil (&r, TYPE_MODE (ftype), &x);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_LROUND):
+ CASE_FLT_FN (BUILT_IN_LLROUND):
+ real_round (&r, TYPE_MODE (ftype), &x);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ REAL_VALUE_TO_INT (&lo, &hi, r);
+ result = build_int_cst_wide (NULL_TREE, lo, hi);
+ if (int_fits_type_p (result, itype))
+ return fold_convert (itype, result);
+ }
+ }
+
+ return fold_fixed_mathfn (fndecl, arglist);
}
/* Fold function call to builtin ffs, clz, ctz, popcount and parity
@@ -5944,10 +7450,8 @@ fold_builtin_ceil (tree exp)
Return NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_bitop (tree exp)
+fold_builtin_bitop (tree fndecl, tree arglist)
{
- tree fndecl = get_callee_fndecl (exp);
- tree arglist = TREE_OPERAND (exp, 1);
tree arg;
if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
@@ -5959,7 +7463,7 @@ fold_builtin_bitop (tree exp)
{
HOST_WIDE_INT hi, width, result;
unsigned HOST_WIDE_INT lo;
- tree type, t;
+ tree type;
type = TREE_TYPE (arg);
width = TYPE_PRECISION (type);
@@ -5981,9 +7485,7 @@ fold_builtin_bitop (tree exp)
switch (DECL_FUNCTION_CODE (fndecl))
{
- case BUILT_IN_FFS:
- case BUILT_IN_FFSL:
- case BUILT_IN_FFSLL:
+ CASE_INT_FN (BUILT_IN_FFS):
if (lo != 0)
result = exact_log2 (lo & -lo) + 1;
else if (hi != 0)
@@ -5992,9 +7494,7 @@ fold_builtin_bitop (tree exp)
result = 0;
break;
- case BUILT_IN_CLZ:
- case BUILT_IN_CLZL:
- case BUILT_IN_CLZLL:
+ CASE_INT_FN (BUILT_IN_CLZ):
if (hi != 0)
result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
else if (lo != 0)
@@ -6003,9 +7503,7 @@ fold_builtin_bitop (tree exp)
result = width;
break;
- case BUILT_IN_CTZ:
- case BUILT_IN_CTZL:
- case BUILT_IN_CTZLL:
+ CASE_INT_FN (BUILT_IN_CTZ):
if (lo != 0)
result = exact_log2 (lo & -lo);
else if (hi != 0)
@@ -6014,9 +7512,7 @@ fold_builtin_bitop (tree exp)
result = width;
break;
- case BUILT_IN_POPCOUNT:
- case BUILT_IN_POPCOUNTL:
- case BUILT_IN_POPCOUNTLL:
+ CASE_INT_FN (BUILT_IN_POPCOUNT):
result = 0;
while (lo)
result++, lo &= lo - 1;
@@ -6024,9 +7520,7 @@ fold_builtin_bitop (tree exp)
result++, hi &= hi - 1;
break;
- case BUILT_IN_PARITY:
- case BUILT_IN_PARITYL:
- case BUILT_IN_PARITYLL:
+ CASE_INT_FN (BUILT_IN_PARITY):
result = 0;
while (lo)
result++, lo &= lo - 1;
@@ -6036,12 +7530,10 @@ fold_builtin_bitop (tree exp)
break;
default:
- abort();
+ gcc_unreachable ();
}
- t = build_int_2 (result, 0);
- TREE_TYPE (t) = TREE_TYPE (exp);
- return t;
+ return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
}
return NULL_TREE;
@@ -6055,44 +7547,42 @@ real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
STRIP_NOPS (expr);
return ((TREE_CODE (expr) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (expr)
- && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
- || (TREE_CODE (expr) == COMPLEX_CST
- && real_dconstp (TREE_REALPART (expr), value)
- && real_zerop (TREE_IMAGPART (expr))));
+ && ! TREE_CONSTANT_OVERFLOW (expr)
+ && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
+ || (TREE_CODE (expr) == COMPLEX_CST
+ && real_dconstp (TREE_REALPART (expr), value)
+ && real_zerop (TREE_IMAGPART (expr))));
}
/* A subroutine of fold_builtin to fold the various logarithmic
- functions. EXP is the CALL_EXPR of a call to a builtin log*
- function. VALUE is the base of the log* function. */
+ functions. EXP is the CALL_EXPR of a call to a builtin logN
+ function. VALUE is the base of the logN function. */
static tree
-fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value)
+fold_builtin_logarithm (tree fndecl, tree arglist,
+ const REAL_VALUE_TYPE *value)
{
- tree arglist = TREE_OPERAND (exp, 1);
-
if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
{
- tree fndecl = get_callee_fndecl (exp);
tree type = TREE_TYPE (TREE_TYPE (fndecl));
tree arg = TREE_VALUE (arglist);
const enum built_in_function fcode = builtin_mathfn_code (arg);
-
- /* Optimize log*(1.0) = 0.0. */
+
+ /* Optimize logN(1.0) = 0.0. */
if (real_onep (arg))
return build_real (type, dconst0);
/* Optimize logN(N) = 1.0. If N can't be truncated to MODE
- exactly, then only do this if flag_unsafe_math_optimizations. */
+ exactly, then only do this if flag_unsafe_math_optimizations. */
if (exact_real_truncate (TYPE_MODE (type), value)
|| flag_unsafe_math_optimizations)
- {
+ {
const REAL_VALUE_TYPE value_truncate =
real_value_truncate (TYPE_MODE (type), *value);
if (real_dconstp (arg, &value_truncate))
return build_real (type, dconst1);
}
-
+
/* Special case, optimize logN(expN(x)) = x. */
if (flag_unsafe_math_optimizations
&& ((value == &dconste
@@ -6103,64 +7593,47 @@ fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value)
&& (fcode == BUILT_IN_EXP2
|| fcode == BUILT_IN_EXP2F
|| fcode == BUILT_IN_EXP2L))
- || (value == &dconst10
- && (fcode == BUILT_IN_EXP10
- || fcode == BUILT_IN_EXP10F
- || fcode == BUILT_IN_EXP10L))))
- return convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
-
- /* Optimize log*(func()) for various exponential functions. We
- want to determine the value "x" and the power "exponent" in
- order to transform logN(x**exponent) into exponent*logN(x). */
+ || (value == &dconst10 && (BUILTIN_EXP10_P (fcode)))))
+ return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
+
+ /* Optimize logN(func()) for various exponential functions. We
+ want to determine the value "x" and the power "exponent" in
+ order to transform logN(x**exponent) into exponent*logN(x). */
if (flag_unsafe_math_optimizations)
- {
+ {
tree exponent = 0, x = 0;
-
+
switch (fcode)
{
- case BUILT_IN_EXP:
- case BUILT_IN_EXPF:
- case BUILT_IN_EXPL:
+ CASE_FLT_FN (BUILT_IN_EXP):
/* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
x = build_real (type,
real_value_truncate (TYPE_MODE (type), dconste));
exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
break;
- case BUILT_IN_EXP2:
- case BUILT_IN_EXP2F:
- case BUILT_IN_EXP2L:
+ CASE_FLT_FN (BUILT_IN_EXP2):
/* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
x = build_real (type, dconst2);
exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
break;
- case BUILT_IN_EXP10:
- case BUILT_IN_EXP10F:
- case BUILT_IN_EXP10L:
- case BUILT_IN_POW10:
- case BUILT_IN_POW10F:
- case BUILT_IN_POW10L:
+ CASE_FLT_FN (BUILT_IN_EXP10):
+ CASE_FLT_FN (BUILT_IN_POW10):
/* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
x = build_real (type, dconst10);
exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
break;
- case BUILT_IN_SQRT:
- case BUILT_IN_SQRTF:
- case BUILT_IN_SQRTL:
+ CASE_FLT_FN (BUILT_IN_SQRT):
/* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
x = TREE_VALUE (TREE_OPERAND (arg, 1));
exponent = build_real (type, dconsthalf);
break;
- case BUILT_IN_CBRT:
- case BUILT_IN_CBRTF:
- case BUILT_IN_CBRTL:
+ CASE_FLT_FN (BUILT_IN_CBRT):
/* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
x = TREE_VALUE (TREE_OPERAND (arg, 1));
exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
dconstthird));
break;
- case BUILT_IN_POW:
- case BUILT_IN_POWF:
- case BUILT_IN_POWL:
+ CASE_FLT_FN (BUILT_IN_POW):
/* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
x = TREE_VALUE (TREE_OPERAND (arg, 1));
exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
@@ -6175,26 +7648,212 @@ fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value)
tree logfn;
arglist = build_tree_list (NULL_TREE, x);
logfn = build_function_call_expr (fndecl, arglist);
- return fold (build (MULT_EXPR, type, exponent, logfn));
+ return fold_build2 (MULT_EXPR, type, exponent, logfn);
}
}
}
return 0;
}
-
+
+/* Fold a builtin function call to pow, powf, or powl. Return
+ NULL_TREE if no simplification can be made. */
+static tree
+fold_builtin_pow (tree fndecl, tree arglist, tree type)
+{
+ tree arg0 = TREE_VALUE (arglist);
+ tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+ if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ /* Optimize pow(1.0,y) = 1.0. */
+ if (real_onep (arg0))
+ return omit_one_operand (type, build_real (type, dconst1), arg1);
+
+ if (TREE_CODE (arg1) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg1))
+ {
+ REAL_VALUE_TYPE cint;
+ REAL_VALUE_TYPE c;
+ HOST_WIDE_INT n;
+
+ c = TREE_REAL_CST (arg1);
+
+ /* Optimize pow(x,0.0) = 1.0. */
+ if (REAL_VALUES_EQUAL (c, dconst0))
+ return omit_one_operand (type, build_real (type, dconst1),
+ arg0);
+
+ /* Optimize pow(x,1.0) = x. */
+ if (REAL_VALUES_EQUAL (c, dconst1))
+ return arg0;
+
+ /* Optimize pow(x,-1.0) = 1.0/x. */
+ if (REAL_VALUES_EQUAL (c, dconstm1))
+ return fold_build2 (RDIV_EXPR, type,
+ build_real (type, dconst1), arg0);
+
+ /* Optimize pow(x,0.5) = sqrt(x). */
+ if (flag_unsafe_math_optimizations
+ && REAL_VALUES_EQUAL (c, dconsthalf))
+ {
+ tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
+
+ if (sqrtfn != NULL_TREE)
+ {
+ tree arglist = build_tree_list (NULL_TREE, arg0);
+ return build_function_call_expr (sqrtfn, arglist);
+ }
+ }
+
+ /* Check for an integer exponent. */
+ n = real_to_integer (&c);
+ real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
+ if (real_identical (&c, &cint))
+ {
+ /* Attempt to evaluate pow at compile-time. */
+ if (TREE_CODE (arg0) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg0))
+ {
+ REAL_VALUE_TYPE x;
+ bool inexact;
+
+ x = TREE_REAL_CST (arg0);
+ inexact = real_powi (&x, TYPE_MODE (type), &x, n);
+ if (flag_unsafe_math_optimizations || !inexact)
+ return build_real (type, x);
+ }
+
+ /* Strip sign ops from even integer powers. */
+ if ((n & 1) == 0 && flag_unsafe_math_optimizations)
+ {
+ tree narg0 = fold_strip_sign_ops (arg0);
+ if (narg0)
+ {
+ arglist = build_tree_list (NULL_TREE, arg1);
+ arglist = tree_cons (NULL_TREE, narg0, arglist);
+ return build_function_call_expr (fndecl, arglist);
+ }
+ }
+ }
+ }
+
+ if (flag_unsafe_math_optimizations)
+ {
+ const enum built_in_function fcode = builtin_mathfn_code (arg0);
+
+ /* Optimize pow(expN(x),y) = expN(x*y). */
+ if (BUILTIN_EXPONENT_P (fcode))
+ {
+ tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
+ arg = fold_build2 (MULT_EXPR, type, arg, arg1);
+ arglist = build_tree_list (NULL_TREE, arg);
+ return build_function_call_expr (expfn, arglist);
+ }
+
+ /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
+ if (BUILTIN_SQRT_P (fcode))
+ {
+ tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+ tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
+ build_real (type, dconsthalf));
+
+ arglist = tree_cons (NULL_TREE, narg0,
+ build_tree_list (NULL_TREE, narg1));
+ return build_function_call_expr (fndecl, arglist);
+ }
+
+ /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
+ if (BUILTIN_CBRT_P (fcode))
+ {
+ tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
+ if (tree_expr_nonnegative_p (arg))
+ {
+ const REAL_VALUE_TYPE dconstroot
+ = real_value_truncate (TYPE_MODE (type), dconstthird);
+ tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
+ build_real (type, dconstroot));
+ arglist = tree_cons (NULL_TREE, arg,
+ build_tree_list (NULL_TREE, narg1));
+ return build_function_call_expr (fndecl, arglist);
+ }
+ }
+
+ /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
+ if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
+ || fcode == BUILT_IN_POWL)
+ {
+ tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+ tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
+ tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
+ arglist = tree_cons (NULL_TREE, arg00,
+ build_tree_list (NULL_TREE, narg1));
+ return build_function_call_expr (fndecl, arglist);
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Fold a builtin function call to powi, powif, or powil. Return
+ NULL_TREE if no simplification can be made. */
+static tree
+fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type)
+{
+ tree arg0 = TREE_VALUE (arglist);
+ tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+ if (!validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ /* Optimize pow(1.0,y) = 1.0. */
+ if (real_onep (arg0))
+ return omit_one_operand (type, build_real (type, dconst1), arg1);
+
+ if (host_integerp (arg1, 0))
+ {
+ HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
+
+ /* Evaluate powi at compile-time. */
+ if (TREE_CODE (arg0) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg0))
+ {
+ REAL_VALUE_TYPE x;
+ x = TREE_REAL_CST (arg0);
+ real_powi (&x, TYPE_MODE (type), &x, c);
+ return build_real (type, x);
+ }
+
+ /* Optimize pow(x,0) = 1.0. */
+ if (c == 0)
+ return omit_one_operand (type, build_real (type, dconst1),
+ arg0);
+
+ /* Optimize pow(x,1) = x. */
+ if (c == 1)
+ return arg0;
+
+ /* Optimize pow(x,-1) = 1.0/x. */
+ if (c == -1)
+ return fold_build2 (RDIV_EXPR, type,
+ build_real (type, dconst1), arg0);
+ }
+
+ return NULL_TREE;
+}
+
/* A subroutine of fold_builtin to fold the various exponent
functions. EXP is the CALL_EXPR of a call to a builtin function.
VALUE is the value which will be raised to a power. */
static tree
-fold_builtin_exponent (tree exp, const REAL_VALUE_TYPE *value)
+fold_builtin_exponent (tree fndecl, tree arglist,
+ const REAL_VALUE_TYPE *value)
{
- tree arglist = TREE_OPERAND (exp, 1);
-
if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
{
- tree fndecl = get_callee_fndecl (exp);
tree type = TREE_TYPE (TREE_TYPE (fndecl));
tree arg = TREE_VALUE (arglist);
@@ -6204,7 +7863,7 @@ fold_builtin_exponent (tree exp, const REAL_VALUE_TYPE *value)
/* Optimize expN(1.0) = N. */
if (real_onep (arg))
- {
+ {
REAL_VALUE_TYPE cst;
real_convert (&cst, TYPE_MODE (type), value);
@@ -6215,7 +7874,7 @@ fold_builtin_exponent (tree exp, const REAL_VALUE_TYPE *value)
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg) == REAL_CST
&& ! TREE_CONSTANT_OVERFLOW (arg))
- {
+ {
REAL_VALUE_TYPE cint;
REAL_VALUE_TYPE c;
HOST_WIDE_INT n;
@@ -6235,7 +7894,7 @@ fold_builtin_exponent (tree exp, const REAL_VALUE_TYPE *value)
/* Optimize expN(logN(x)) = x. */
if (flag_unsafe_math_optimizations)
- {
+ {
const enum built_in_function fcode = builtin_mathfn_code (arg);
if ((value == &dconste
@@ -6250,52 +7909,142 @@ fold_builtin_exponent (tree exp, const REAL_VALUE_TYPE *value)
&& (fcode == BUILT_IN_LOG10
|| fcode == BUILT_IN_LOG10F
|| fcode == BUILT_IN_LOG10L)))
- return convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
+ return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
}
}
return 0;
}
-/* Fold function call to builtin memcpy. Return
+/* Return true if VAR is a VAR_DECL or a component thereof. */
+
+static bool
+var_decl_component_p (tree var)
+{
+ tree inner = var;
+ while (handled_component_p (inner))
+ inner = TREE_OPERAND (inner, 0);
+ return SSA_VAR_P (inner);
+}
+
+/* Fold function call to builtin memset. Return
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_memcpy (tree exp)
+fold_builtin_memset (tree arglist, tree type, bool ignore)
{
- tree arglist = TREE_OPERAND (exp, 1);
- tree dest, src, len;
+ tree dest, c, len, var, ret;
+ unsigned HOST_WIDE_INT length, cval;
if (!validate_arglist (arglist,
- POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
dest = TREE_VALUE (arglist);
- src = TREE_VALUE (TREE_CHAIN (arglist));
+ c = TREE_VALUE (TREE_CHAIN (arglist));
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ if (! host_integerp (len, 1))
+ return 0;
+
/* If the LEN parameter is zero, return DEST. */
if (integer_zerop (len))
- return omit_one_operand (TREE_TYPE (exp), dest, src);
+ return omit_one_operand (type, dest, c);
- /* If SRC and DEST are the same (and not volatile), return DEST. */
- if (operand_equal_p (src, dest, 0))
- return omit_one_operand (TREE_TYPE (exp), dest, len);
+ if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
+ return 0;
- return 0;
+ var = dest;
+ STRIP_NOPS (var);
+ if (TREE_CODE (var) != ADDR_EXPR)
+ return 0;
+
+ var = TREE_OPERAND (var, 0);
+ if (TREE_THIS_VOLATILE (var))
+ return 0;
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
+ && !POINTER_TYPE_P (TREE_TYPE (var)))
+ return 0;
+
+ if (! var_decl_component_p (var))
+ return 0;
+
+ length = tree_low_cst (len, 1);
+ if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length
+ || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
+ < (int) length)
+ return 0;
+
+ if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
+ return 0;
+
+ if (integer_zerop (c))
+ cval = 0;
+ else
+ {
+ if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
+ return 0;
+
+ cval = tree_low_cst (c, 1);
+ cval &= 0xff;
+ cval |= cval << 8;
+ cval |= cval << 16;
+ cval |= (cval << 31) << 1;
+ }
+
+ ret = build_int_cst_type (TREE_TYPE (var), cval);
+ ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
+ if (ignore)
+ return ret;
+
+ return omit_one_operand (type, dest, ret);
}
-/* Fold function call to builtin mempcpy. Return
+/* Fold function call to builtin memset. Return
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_mempcpy (tree exp)
+fold_builtin_bzero (tree arglist, bool ignore)
{
- tree arglist = TREE_OPERAND (exp, 1);
- tree dest, src, len;
+ tree dest, size, newarglist;
- if (!validate_arglist (arglist,
- POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ if (!ignore)
+ return 0;
+
+ dest = TREE_VALUE (arglist);
+ size = TREE_VALUE (TREE_CHAIN (arglist));
+
+ /* New argument list transforming bzero(ptr x, int y) to
+ memset(ptr x, int 0, size_t y). This is done this way
+ so that if it isn't expanded inline, we fallback to
+ calling bzero instead of memset. */
+
+ newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
+ newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
+ newarglist = tree_cons (NULL_TREE, dest, newarglist);
+ return fold_builtin_memset (newarglist, void_type_node, ignore);
+}
+
+/* Fold function call to builtin mem{{,p}cpy,move}. Return
+ NULL_TREE if no simplification can be made.
+ If ENDP is 0, return DEST (like memcpy).
+ If ENDP is 1, return DEST+LEN (like mempcpy).
+ If ENDP is 2, return DEST+LEN-1 (like stpcpy).
+ If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
+ (memmove). */
+
+static tree
+fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp)
+{
+ tree dest, src, len, destvar, srcvar, expr;
+ unsigned HOST_WIDE_INT length;
+
+ if (! validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
dest = TREE_VALUE (arglist);
@@ -6304,55 +8053,133 @@ fold_builtin_mempcpy (tree exp)
/* If the LEN parameter is zero, return DEST. */
if (integer_zerop (len))
- return omit_one_operand (TREE_TYPE (exp), dest, src);
+ return omit_one_operand (type, dest, src);
- /* If SRC and DEST are the same (and not volatile), return DEST+LEN. */
+ /* If SRC and DEST are the same (and not volatile), return
+ DEST{,+LEN,+LEN-1}. */
if (operand_equal_p (src, dest, 0))
+ expr = len;
+ else
{
- tree temp = convert (TREE_TYPE (dest), len);
- temp = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, len));
- return convert (TREE_TYPE (exp), temp);
+ if (! host_integerp (len, 1))
+ return 0;
+
+ if (TREE_SIDE_EFFECTS (dest) || TREE_SIDE_EFFECTS (src))
+ return 0;
+
+ destvar = dest;
+ STRIP_NOPS (destvar);
+ if (TREE_CODE (destvar) != ADDR_EXPR)
+ return 0;
+
+ destvar = TREE_OPERAND (destvar, 0);
+ if (TREE_THIS_VOLATILE (destvar))
+ return 0;
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (destvar))
+ && !POINTER_TYPE_P (TREE_TYPE (destvar))
+ && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (destvar)))
+ return 0;
+
+ if (! var_decl_component_p (destvar))
+ return 0;
+
+ srcvar = src;
+ STRIP_NOPS (srcvar);
+ if (TREE_CODE (srcvar) != ADDR_EXPR)
+ return 0;
+
+ srcvar = TREE_OPERAND (srcvar, 0);
+ if (TREE_THIS_VOLATILE (srcvar))
+ return 0;
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
+ && !POINTER_TYPE_P (TREE_TYPE (srcvar))
+ && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (srcvar)))
+ return 0;
+
+ if (! var_decl_component_p (srcvar))
+ return 0;
+
+ length = tree_low_cst (len, 1);
+ if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (destvar))) != length
+ || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
+ < (int) length
+ || GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (srcvar))) != length
+ || get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
+ < (int) length)
+ return 0;
+
+ if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
+ || POINTER_TYPE_P (TREE_TYPE (srcvar)))
+ && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
+ || POINTER_TYPE_P (TREE_TYPE (destvar))))
+ expr = fold_convert (TREE_TYPE (destvar), srcvar);
+ else
+ expr = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (destvar), srcvar);
+ expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
}
- return 0;
+ if (ignore)
+ return expr;
+
+ if (endp == 0 || endp == 3)
+ return omit_one_operand (type, dest, expr);
+
+ if (expr == len)
+ expr = 0;
+
+ if (endp == 2)
+ len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
+ ssize_int (1));
+
+ len = fold_convert (TREE_TYPE (dest), len);
+ dest = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
+ dest = fold_convert (type, dest);
+ if (expr)
+ dest = omit_one_operand (type, dest, expr);
+ return dest;
}
-/* Fold function call to builtin memmove. Return
- NULL_TREE if no simplification can be made. */
+/* Fold function call to builtin bcopy. Return NULL_TREE if no
+ simplification can be made. */
static tree
-fold_builtin_memmove (tree exp)
+fold_builtin_bcopy (tree arglist, bool ignore)
{
- tree arglist = TREE_OPERAND (exp, 1);
- tree dest, src, len;
+ tree src, dest, size, newarglist;
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
- dest = TREE_VALUE (arglist);
- src = TREE_VALUE (TREE_CHAIN (arglist));
- len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ if (! ignore)
+ return 0;
- /* If the LEN parameter is zero, return DEST. */
- if (integer_zerop (len))
- return omit_one_operand (TREE_TYPE (exp), dest, src);
+ src = TREE_VALUE (arglist);
+ dest = TREE_VALUE (TREE_CHAIN (arglist));
+ size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- /* If SRC and DEST are the same (and not volatile), return DEST. */
- if (operand_equal_p (src, dest, 0))
- return omit_one_operand (TREE_TYPE (exp), dest, len);
+ /* New argument list transforming bcopy(ptr x, ptr y, int z) to
+ memmove(ptr y, ptr x, size_t z). This is done this way
+ so that if it isn't expanded inline, we fallback to
+ calling bcopy instead of memmove. */
- return 0;
+ newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
+ newarglist = tree_cons (NULL_TREE, src, newarglist);
+ newarglist = tree_cons (NULL_TREE, dest, newarglist);
+
+ return fold_builtin_memory_op (newarglist, void_type_node, true, /*endp=*/3);
}
-/* Fold function call to builtin strcpy. Return
- NULL_TREE if no simplification can be made. */
+/* Fold function call to builtin strcpy. If LEN is not NULL, it represents
+ the length of the string to be copied. Return NULL_TREE if no
+ simplification can be made. */
-static tree
-fold_builtin_strcpy (tree exp)
+tree
+fold_builtin_strcpy (tree fndecl, tree arglist, tree len)
{
- tree arglist = TREE_OPERAND (exp, 1);
- tree dest, src;
+ tree dest, src, fn;
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
@@ -6363,19 +8190,38 @@ fold_builtin_strcpy (tree exp)
/* If SRC and DEST are the same (and not volatile), return DEST. */
if (operand_equal_p (src, dest, 0))
- return convert (TREE_TYPE (exp), dest);
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
- return 0;
+ if (optimize_size)
+ return 0;
+
+ fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ if (!fn)
+ return 0;
+
+ if (!len)
+ {
+ len = c_strlen (src, 1);
+ if (! len || TREE_SIDE_EFFECTS (len))
+ return 0;
+ }
+
+ len = size_binop (PLUS_EXPR, len, ssize_int (1));
+ arglist = build_tree_list (NULL_TREE, len);
+ arglist = tree_cons (NULL_TREE, src, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
+ build_function_call_expr (fn, arglist));
}
-/* Fold function call to builtin strncpy. Return
- NULL_TREE if no simplification can be made. */
+/* Fold function call to builtin strncpy. If SLEN is not NULL, it represents
+ the length of the source string. Return NULL_TREE if no simplification
+ can be made. */
-static tree
-fold_builtin_strncpy (tree exp)
+tree
+fold_builtin_strncpy (tree fndecl, tree arglist, tree slen)
{
- tree arglist = TREE_OPERAND (exp, 1);
- tree dest, src, len;
+ tree dest, src, len, fn;
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -6387,19 +8233,44 @@ fold_builtin_strncpy (tree exp)
/* If the LEN parameter is zero, return DEST. */
if (integer_zerop (len))
- return omit_one_operand (TREE_TYPE (exp), dest, src);
+ return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
- return 0;
+ /* We can't compare slen with len as constants below if len is not a
+ constant. */
+ if (len == 0 || TREE_CODE (len) != INTEGER_CST)
+ return 0;
+
+ if (!slen)
+ slen = c_strlen (src, 1);
+
+ /* Now, we must be passed a constant src ptr parameter. */
+ if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
+ return 0;
+
+ slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
+
+ /* We do not support simplification of this case, though we do
+ support it when expanding trees into RTL. */
+ /* FIXME: generate a call to __builtin_memset. */
+ if (tree_int_cst_lt (slen, len))
+ return 0;
+
+ /* OK transform into builtin memcpy. */
+ fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ if (!fn)
+ return 0;
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
+ build_function_call_expr (fn, arglist));
}
/* Fold function call to builtin memcmp. Return
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_memcmp (tree exp)
+fold_builtin_memcmp (tree arglist)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree arg1, arg2, len;
+ const char *p1, *p2;
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -6411,14 +8282,50 @@ fold_builtin_memcmp (tree exp)
/* If the LEN parameter is zero, return zero. */
if (integer_zerop (len))
- {
- tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
- return omit_one_operand (TREE_TYPE (exp), temp, arg1);
- }
+ return omit_two_operands (integer_type_node, integer_zero_node,
+ arg1, arg2);
/* If ARG1 and ARG2 are the same (and not volatile), return zero. */
if (operand_equal_p (arg1, arg2, 0))
- return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
+ return omit_one_operand (integer_type_node, integer_zero_node, len);
+
+ p1 = c_getstr (arg1);
+ p2 = c_getstr (arg2);
+
+ /* If all arguments are constant, and the value of len is not greater
+ than the lengths of arg1 and arg2, evaluate at compile-time. */
+ if (host_integerp (len, 1) && p1 && p2
+ && compare_tree_int (len, strlen (p1) + 1) <= 0
+ && compare_tree_int (len, strlen (p2) + 1) <= 0)
+ {
+ const int r = memcmp (p1, p2, tree_low_cst (len, 1));
+
+ if (r > 0)
+ return integer_one_node;
+ else if (r < 0)
+ return integer_minus_one_node;
+ else
+ return integer_zero_node;
+ }
+
+ /* If len parameter is one, return an expression corresponding to
+ (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
+ if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
+ {
+ tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
+ tree cst_uchar_ptr_node
+ = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
+ tree ind1 = fold_convert (integer_type_node,
+ build1 (INDIRECT_REF, cst_uchar_node,
+ fold_convert (cst_uchar_ptr_node,
+ arg1)));
+ tree ind2 = fold_convert (integer_type_node,
+ build1 (INDIRECT_REF, cst_uchar_node,
+ fold_convert (cst_uchar_ptr_node,
+ arg2)));
+ return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
+ }
return 0;
}
@@ -6427,14 +8334,12 @@ fold_builtin_memcmp (tree exp)
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_strcmp (tree exp)
+fold_builtin_strcmp (tree arglist)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree arg1, arg2;
const char *p1, *p2;
- if (!validate_arglist (arglist,
- POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
arg1 = TREE_VALUE (arglist);
@@ -6442,22 +8347,47 @@ fold_builtin_strcmp (tree exp)
/* If ARG1 and ARG2 are the same (and not volatile), return zero. */
if (operand_equal_p (arg1, arg2, 0))
- return convert (TREE_TYPE (exp), integer_zero_node);
+ return integer_zero_node;
p1 = c_getstr (arg1);
p2 = c_getstr (arg2);
if (p1 && p2)
{
- tree temp;
const int i = strcmp (p1, p2);
if (i < 0)
- temp = integer_minus_one_node;
+ return integer_minus_one_node;
else if (i > 0)
- temp = integer_one_node;
+ return integer_one_node;
else
- temp = integer_zero_node;
- return convert (TREE_TYPE (exp), temp);
+ return integer_zero_node;
+ }
+
+ /* If the second arg is "", return *(const unsigned char*)arg1. */
+ if (p2 && *p2 == '\0')
+ {
+ tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
+ tree cst_uchar_ptr_node
+ = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
+ return fold_convert (integer_type_node,
+ build1 (INDIRECT_REF, cst_uchar_node,
+ fold_convert (cst_uchar_ptr_node,
+ arg1)));
+ }
+
+ /* If the first arg is "", return -*(const unsigned char*)arg2. */
+ if (p1 && *p1 == '\0')
+ {
+ tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
+ tree cst_uchar_ptr_node
+ = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
+ tree temp = fold_convert (integer_type_node,
+ build1 (INDIRECT_REF, cst_uchar_node,
+ fold_convert (cst_uchar_ptr_node,
+ arg2)));
+ return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
}
return 0;
@@ -6467,9 +8397,8 @@ fold_builtin_strcmp (tree exp)
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_strncmp (tree exp)
+fold_builtin_strncmp (tree arglist)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree arg1, arg2, len;
const char *p1, *p2;
@@ -6483,455 +8412,764 @@ fold_builtin_strncmp (tree exp)
/* If the LEN parameter is zero, return zero. */
if (integer_zerop (len))
- {
- tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
- return omit_one_operand (TREE_TYPE (exp), temp, arg1);
- }
+ return omit_two_operands (integer_type_node, integer_zero_node,
+ arg1, arg2);
/* If ARG1 and ARG2 are the same (and not volatile), return zero. */
if (operand_equal_p (arg1, arg2, 0))
- return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
+ return omit_one_operand (integer_type_node, integer_zero_node, len);
p1 = c_getstr (arg1);
p2 = c_getstr (arg2);
if (host_integerp (len, 1) && p1 && p2)
{
- tree temp;
const int i = strncmp (p1, p2, tree_low_cst (len, 1));
- if (i < 0)
- temp = integer_minus_one_node;
- else if (i > 0)
- temp = integer_one_node;
+ if (i > 0)
+ return integer_one_node;
+ else if (i < 0)
+ return integer_minus_one_node;
else
- temp = integer_zero_node;
- return convert (TREE_TYPE (exp), temp);
+ return integer_zero_node;
+ }
+
+ /* If the second arg is "", and the length is greater than zero,
+ return *(const unsigned char*)arg1. */
+ if (p2 && *p2 == '\0'
+ && TREE_CODE (len) == INTEGER_CST
+ && tree_int_cst_sgn (len) == 1)
+ {
+ tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
+ tree cst_uchar_ptr_node
+ = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
+ return fold_convert (integer_type_node,
+ build1 (INDIRECT_REF, cst_uchar_node,
+ fold_convert (cst_uchar_ptr_node,
+ arg1)));
+ }
+
+ /* If the first arg is "", and the length is greater than zero,
+ return -*(const unsigned char*)arg2. */
+ if (p1 && *p1 == '\0'
+ && TREE_CODE (len) == INTEGER_CST
+ && tree_int_cst_sgn (len) == 1)
+ {
+ tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
+ tree cst_uchar_ptr_node
+ = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
+ tree temp = fold_convert (integer_type_node,
+ build1 (INDIRECT_REF, cst_uchar_node,
+ fold_convert (cst_uchar_ptr_node,
+ arg2)));
+ return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
+ }
+
+ /* If len parameter is one, return an expression corresponding to
+ (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
+ if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
+ {
+ tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
+ tree cst_uchar_ptr_node
+ = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
+
+ tree ind1 = fold_convert (integer_type_node,
+ build1 (INDIRECT_REF, cst_uchar_node,
+ fold_convert (cst_uchar_ptr_node,
+ arg1)));
+ tree ind2 = fold_convert (integer_type_node,
+ build1 (INDIRECT_REF, cst_uchar_node,
+ fold_convert (cst_uchar_ptr_node,
+ arg2)));
+ return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
}
return 0;
}
-/* Used by constant folding to eliminate some builtin calls early. EXP is
- the CALL_EXPR of a call to a builtin function. */
+/* Fold function call to builtin signbit, signbitf or signbitl. Return
+ NULL_TREE if no simplification can be made. */
-tree
-fold_builtin (tree exp)
+static tree
+fold_builtin_signbit (tree fndecl, tree arglist)
{
- tree fndecl = get_callee_fndecl (exp);
- tree arglist = TREE_OPERAND (exp, 1);
tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ tree arg, temp;
- if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ arg = TREE_VALUE (arglist);
+
+ /* If ARG is a compile-time constant, determine the result. */
+ if (TREE_CODE (arg) == REAL_CST
+ && !TREE_CONSTANT_OVERFLOW (arg))
+ {
+ REAL_VALUE_TYPE c;
+
+ c = TREE_REAL_CST (arg);
+ temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
+ return fold_convert (type, temp);
+ }
+
+ /* If ARG is non-negative, the result is always zero. */
+ if (tree_expr_nonnegative_p (arg))
+ return omit_one_operand (type, integer_zero_node, arg);
+
+ /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
+ if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
+ return fold_build2 (LT_EXPR, type, arg,
+ build_real (TREE_TYPE (arg), dconst0));
+
+ return NULL_TREE;
+}
+
+/* Fold function call to builtin copysign, copysignf or copysignl.
+ Return NULL_TREE if no simplification can be made. */
+
+static tree
+fold_builtin_copysign (tree fndecl, tree arglist, tree type)
+{
+ tree arg1, arg2, tem;
+
+ if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+ return NULL_TREE;
+
+ arg1 = TREE_VALUE (arglist);
+ arg2 = TREE_VALUE (TREE_CHAIN (arglist));
+
+ /* copysign(X,X) is X. */
+ if (operand_equal_p (arg1, arg2, 0))
+ return fold_convert (type, arg1);
+
+ /* If ARG1 and ARG2 are compile-time constants, determine the result. */
+ if (TREE_CODE (arg1) == REAL_CST
+ && TREE_CODE (arg2) == REAL_CST
+ && !TREE_CONSTANT_OVERFLOW (arg1)
+ && !TREE_CONSTANT_OVERFLOW (arg2))
+ {
+ REAL_VALUE_TYPE c1, c2;
+
+ c1 = TREE_REAL_CST (arg1);
+ c2 = TREE_REAL_CST (arg2);
+ /* c1.sign := c2.sign. */
+ real_copysign (&c1, &c2);
+ return build_real (type, c1);
+ }
+
+ /* copysign(X, Y) is fabs(X) when Y is always non-negative.
+ Remember to evaluate Y for side-effects. */
+ if (tree_expr_nonnegative_p (arg2))
+ return omit_one_operand (type,
+ fold_build1 (ABS_EXPR, type, arg1),
+ arg2);
+
+ /* Strip sign changing operations for the first argument. */
+ tem = fold_strip_sign_ops (arg1);
+ if (tem)
+ {
+ arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist));
+ return build_function_call_expr (fndecl, arglist);
+ }
+
+ return NULL_TREE;
+}
+
+/* Fold a call to builtin isascii. */
+
+static tree
+fold_builtin_isascii (tree arglist)
+{
+ if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
return 0;
+ else
+ {
+ /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
+ tree arg = TREE_VALUE (arglist);
- switch (DECL_FUNCTION_CODE (fndecl))
+ arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
+ build_int_cst (NULL_TREE,
+ ~ (unsigned HOST_WIDE_INT) 0x7f));
+ arg = fold_build2 (EQ_EXPR, integer_type_node,
+ arg, integer_zero_node);
+
+ if (in_gimple_form && !TREE_CONSTANT (arg))
+ return NULL_TREE;
+ else
+ return arg;
+ }
+}
+
+/* Fold a call to builtin toascii. */
+
+static tree
+fold_builtin_toascii (tree arglist)
+{
+ if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+ else
{
- case BUILT_IN_CONSTANT_P:
- return fold_builtin_constant_p (arglist);
+ /* Transform toascii(c) -> (c & 0x7f). */
+ tree arg = TREE_VALUE (arglist);
- case BUILT_IN_CLASSIFY_TYPE:
- return fold_builtin_classify_type (arglist);
+ return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
+ build_int_cst (NULL_TREE, 0x7f));
+ }
+}
- case BUILT_IN_STRLEN:
- if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
- {
- tree len = c_strlen (TREE_VALUE (arglist), 0);
- if (len)
- {
- /* Convert from the internal "sizetype" type to "size_t". */
- if (size_type_node)
- len = convert (size_type_node, len);
- return len;
- }
- }
- break;
+/* Fold a call to builtin isdigit. */
- case BUILT_IN_FABS:
- case BUILT_IN_FABSF:
- case BUILT_IN_FABSL:
- if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
- return fold (build1 (ABS_EXPR, type, TREE_VALUE (arglist)));
- break;
+static tree
+fold_builtin_isdigit (tree arglist)
+{
+ if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
+ /* According to the C standard, isdigit is unaffected by locale.
+ However, it definitely is affected by the target character set. */
+ tree arg;
+ unsigned HOST_WIDE_INT target_digit0
+ = lang_hooks.to_target_charset ('0');
+
+ if (target_digit0 == 0)
+ return NULL_TREE;
+
+ arg = fold_convert (unsigned_type_node, TREE_VALUE (arglist));
+ arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
+ build_int_cst (unsigned_type_node, target_digit0));
+ arg = fold_build2 (LE_EXPR, integer_type_node, arg,
+ build_int_cst (unsigned_type_node, 9));
+ if (in_gimple_form && !TREE_CONSTANT (arg))
+ return NULL_TREE;
+ else
+ return arg;
+ }
+}
- case BUILT_IN_CABS:
- case BUILT_IN_CABSF:
- case BUILT_IN_CABSL:
- return fold_builtin_cabs (fndecl, arglist, type);
+/* Fold a call to fabs, fabsf or fabsl. */
- case BUILT_IN_SQRT:
- case BUILT_IN_SQRTF:
- case BUILT_IN_SQRTL:
- if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
- {
- enum built_in_function fcode;
- tree arg = TREE_VALUE (arglist);
+static tree
+fold_builtin_fabs (tree arglist, tree type)
+{
+ tree arg;
- /* Optimize sqrt of constant value. */
- if (TREE_CODE (arg) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (arg))
- {
- REAL_VALUE_TYPE r, x;
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return 0;
- x = TREE_REAL_CST (arg);
- if (real_sqrt (&r, TYPE_MODE (type), &x)
- || (!flag_trapping_math && !flag_errno_math))
- return build_real (type, r);
- }
+ arg = TREE_VALUE (arglist);
+ arg = fold_convert (type, arg);
+ if (TREE_CODE (arg) == REAL_CST)
+ return fold_abs_const (arg, type);
+ return fold_build1 (ABS_EXPR, type, arg);
+}
- /* Optimize sqrt(exp(x)) = exp(x*0.5). */
- fcode = builtin_mathfn_code (arg);
- if (flag_unsafe_math_optimizations
- && (fcode == BUILT_IN_EXP
- || fcode == BUILT_IN_EXPF
- || fcode == BUILT_IN_EXPL))
- {
- tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
- arg = fold (build (MULT_EXPR, type,
- TREE_VALUE (TREE_OPERAND (arg, 1)),
- build_real (type, dconsthalf)));
- arglist = build_tree_list (NULL_TREE, arg);
- return build_function_call_expr (expfn, arglist);
- }
+/* Fold a call to abs, labs, llabs or imaxabs. */
- /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
- if (flag_unsafe_math_optimizations
- && (fcode == BUILT_IN_POW
- || fcode == BUILT_IN_POWF
- || fcode == BUILT_IN_POWL))
- {
- tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
- tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
- tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
- tree narg1;
- if (!tree_expr_nonnegative_p (arg0))
- arg0 = build1 (ABS_EXPR, type, arg0);
- narg1 = fold (build (MULT_EXPR, type, arg1,
- build_real (type, dconsthalf)));
- arglist = tree_cons (NULL_TREE, arg0,
- build_tree_list (NULL_TREE, narg1));
- return build_function_call_expr (powfn, arglist);
- }
- }
- break;
+static tree
+fold_builtin_abs (tree arglist, tree type)
+{
+ tree arg;
- case BUILT_IN_SIN:
- case BUILT_IN_SINF:
- case BUILT_IN_SINL:
- if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
- {
- tree arg = TREE_VALUE (arglist);
+ if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
+ return 0;
- /* Optimize sin(0.0) = 0.0. */
- if (real_zerop (arg))
- return arg;
- }
- break;
+ arg = TREE_VALUE (arglist);
+ arg = fold_convert (type, arg);
+ if (TREE_CODE (arg) == INTEGER_CST)
+ return fold_abs_const (arg, type);
+ return fold_build1 (ABS_EXPR, type, arg);
+}
- case BUILT_IN_COS:
- case BUILT_IN_COSF:
- case BUILT_IN_COSL:
- if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
- {
- tree arg = TREE_VALUE (arglist);
+/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
+ EXP is the CALL_EXPR for the call. */
- /* Optimize cos(0.0) = 1.0. */
- if (real_zerop (arg))
- return build_real (type, dconst1);
+static tree
+fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
+{
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ tree arg;
+ REAL_VALUE_TYPE r;
- /* Optimize cos(-x) into cos(x). */
- if (TREE_CODE (arg) == NEGATE_EXPR)
- {
- tree arglist = build_tree_list (NULL_TREE,
- TREE_OPERAND (arg, 0));
- return build_function_call_expr (fndecl, arglist);
- }
+ if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ {
+ /* Check that we have exactly one argument. */
+ if (arglist == 0)
+ {
+ error ("too few arguments to function %qs",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ return error_mark_node;
}
- break;
+ else if (TREE_CHAIN (arglist) != 0)
+ {
+ error ("too many arguments to function %qs",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ return error_mark_node;
+ }
+ else
+ {
+ error ("non-floating-point argument to function %qs",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ return error_mark_node;
+ }
+ }
- case BUILT_IN_EXP:
- case BUILT_IN_EXPF:
- case BUILT_IN_EXPL:
- return fold_builtin_exponent (exp, &dconste);
- case BUILT_IN_EXP2:
- case BUILT_IN_EXP2F:
- case BUILT_IN_EXP2L:
- return fold_builtin_exponent (exp, &dconst2);
- case BUILT_IN_EXP10:
- case BUILT_IN_EXP10F:
- case BUILT_IN_EXP10L:
- case BUILT_IN_POW10:
- case BUILT_IN_POW10F:
- case BUILT_IN_POW10L:
- return fold_builtin_exponent (exp, &dconst10);
- case BUILT_IN_LOG:
- case BUILT_IN_LOGF:
- case BUILT_IN_LOGL:
- return fold_builtin_logarithm (exp, &dconste);
- break;
- case BUILT_IN_LOG2:
- case BUILT_IN_LOG2F:
- case BUILT_IN_LOG2L:
- return fold_builtin_logarithm (exp, &dconst2);
- break;
- case BUILT_IN_LOG10:
- case BUILT_IN_LOG10F:
- case BUILT_IN_LOG10L:
- return fold_builtin_logarithm (exp, &dconst10);
- break;
+ arg = TREE_VALUE (arglist);
+ switch (builtin_index)
+ {
+ case BUILT_IN_ISINF:
+ if (!MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
+ return omit_one_operand (type, integer_zero_node, arg);
- case BUILT_IN_TAN:
- case BUILT_IN_TANF:
- case BUILT_IN_TANL:
- if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ if (TREE_CODE (arg) == REAL_CST)
{
- enum built_in_function fcode;
- tree arg = TREE_VALUE (arglist);
+ r = TREE_REAL_CST (arg);
+ if (real_isinf (&r))
+ return real_compare (GT_EXPR, &r, &dconst0)
+ ? integer_one_node : integer_minus_one_node;
+ else
+ return integer_zero_node;
+ }
- /* Optimize tan(0.0) = 0.0. */
- if (real_zerop (arg))
- return arg;
+ return NULL_TREE;
- /* Optimize tan(atan(x)) = x. */
- fcode = builtin_mathfn_code (arg);
- if (flag_unsafe_math_optimizations
- && (fcode == BUILT_IN_ATAN
- || fcode == BUILT_IN_ATANF
- || fcode == BUILT_IN_ATANL))
- return TREE_VALUE (TREE_OPERAND (arg, 1));
- }
- break;
+ case BUILT_IN_FINITE:
+ if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg)))
+ && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
+ return omit_one_operand (type, integer_zero_node, arg);
- case BUILT_IN_ATAN:
- case BUILT_IN_ATANF:
- case BUILT_IN_ATANL:
- if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ if (TREE_CODE (arg) == REAL_CST)
{
- tree arg = TREE_VALUE (arglist);
+ r = TREE_REAL_CST (arg);
+ return real_isinf (&r) || real_isnan (&r)
+ ? integer_zero_node : integer_one_node;
+ }
- /* Optimize atan(0.0) = 0.0. */
- if (real_zerop (arg))
- return arg;
+ return NULL_TREE;
- /* Optimize atan(1.0) = pi/4. */
- if (real_onep (arg))
- {
- REAL_VALUE_TYPE cst;
+ case BUILT_IN_ISNAN:
+ if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg))))
+ return omit_one_operand (type, integer_zero_node, arg);
- real_convert (&cst, TYPE_MODE (type), &dconstpi);
- cst.exp -= 2;
- return build_real (type, cst);
- }
+ if (TREE_CODE (arg) == REAL_CST)
+ {
+ r = TREE_REAL_CST (arg);
+ return real_isnan (&r) ? integer_one_node : integer_zero_node;
}
- break;
- case BUILT_IN_POW:
- case BUILT_IN_POWF:
- case BUILT_IN_POWL:
- if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+ arg = builtin_save_expr (arg);
+ return fold_build2 (UNORDERED_EXPR, type, arg, arg);
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Fold a call to an unordered comparison function such as
+ __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
+ being called and ARGLIST is the argument list for the call.
+ UNORDERED_CODE and ORDERED_CODE are comparison codes that give
+ the opposite of the desired result. UNORDERED_CODE is used
+ for modes that can hold NaNs and ORDERED_CODE is used for
+ the rest. */
+
+static tree
+fold_builtin_unordered_cmp (tree fndecl, tree arglist,
+ enum tree_code unordered_code,
+ enum tree_code ordered_code)
+{
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ enum tree_code code;
+ tree arg0, arg1;
+ tree type0, type1;
+ enum tree_code code0, code1;
+ tree cmp_type = NULL_TREE;
+
+ if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+ {
+ /* Check that we have exactly two arguments. */
+ if (arglist == 0 || TREE_CHAIN (arglist) == 0)
+ {
+ error ("too few arguments to function %qs",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ return error_mark_node;
+ }
+ else if (TREE_CHAIN (TREE_CHAIN (arglist)) != 0)
{
- enum built_in_function fcode;
- tree arg0 = TREE_VALUE (arglist);
- tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ error ("too many arguments to function %qs",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ return error_mark_node;
+ }
+ }
- /* Optimize pow(1.0,y) = 1.0. */
- if (real_onep (arg0))
- return omit_one_operand (type, build_real (type, dconst1), arg1);
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- if (TREE_CODE (arg1) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (arg1))
- {
- REAL_VALUE_TYPE c;
- c = TREE_REAL_CST (arg1);
-
- /* Optimize pow(x,0.0) = 1.0. */
- if (REAL_VALUES_EQUAL (c, dconst0))
- return omit_one_operand (type, build_real (type, dconst1),
- arg0);
-
- /* Optimize pow(x,1.0) = x. */
- if (REAL_VALUES_EQUAL (c, dconst1))
- return arg0;
-
- /* Optimize pow(x,-1.0) = 1.0/x. */
- if (REAL_VALUES_EQUAL (c, dconstm1))
- return fold (build (RDIV_EXPR, type,
- build_real (type, dconst1),
- arg0));
-
- /* Optimize pow(x,0.5) = sqrt(x). */
- if (flag_unsafe_math_optimizations
- && REAL_VALUES_EQUAL (c, dconsthalf))
- {
- tree sqrtfn;
-
- fcode = DECL_FUNCTION_CODE (fndecl);
- if (fcode == BUILT_IN_POW)
- sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
- else if (fcode == BUILT_IN_POWF)
- sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
- else if (fcode == BUILT_IN_POWL)
- sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
- else
- sqrtfn = NULL_TREE;
+ type0 = TREE_TYPE (arg0);
+ type1 = TREE_TYPE (arg1);
- if (sqrtfn != NULL_TREE)
- {
- tree arglist = build_tree_list (NULL_TREE, arg0);
- return build_function_call_expr (sqrtfn, arglist);
- }
- }
+ code0 = TREE_CODE (type0);
+ code1 = TREE_CODE (type1);
- /* Attempt to evaluate pow at compile-time. */
- if (TREE_CODE (arg0) == REAL_CST
- && ! TREE_CONSTANT_OVERFLOW (arg0))
- {
- REAL_VALUE_TYPE cint;
- HOST_WIDE_INT n;
+ if (code0 == REAL_TYPE && code1 == REAL_TYPE)
+ /* Choose the wider of two real types. */
+ cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
+ ? type0 : type1;
+ else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
+ cmp_type = type0;
+ else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
+ cmp_type = type1;
+ else
+ {
+ error ("non-floating-point argument to function %qs",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ return error_mark_node;
+ }
- n = real_to_integer (&c);
- real_from_integer (&cint, VOIDmode, n,
- n < 0 ? -1 : 0, 0);
- if (real_identical (&c, &cint))
- {
- REAL_VALUE_TYPE x;
- bool inexact;
+ arg0 = fold_convert (cmp_type, arg0);
+ arg1 = fold_convert (cmp_type, arg1);
- x = TREE_REAL_CST (arg0);
- inexact = real_powi (&x, TYPE_MODE (type), &x, n);
- if (flag_unsafe_math_optimizations || !inexact)
- return build_real (type, x);
- }
- }
- }
+ if (unordered_code == UNORDERED_EXPR)
+ {
+ if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ return omit_two_operands (type, integer_zero_node, arg0, arg1);
+ return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
+ }
- /* Optimize pow(exp(x),y) = exp(x*y). */
- fcode = builtin_mathfn_code (arg0);
- if (flag_unsafe_math_optimizations
- && (fcode == BUILT_IN_EXP
- || fcode == BUILT_IN_EXPF
- || fcode == BUILT_IN_EXPL))
- {
- tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
- tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
- arg = fold (build (MULT_EXPR, type, arg, arg1));
- arglist = build_tree_list (NULL_TREE, arg);
- return build_function_call_expr (expfn, arglist);
- }
+ code = MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
+ : ordered_code;
+ return fold_build1 (TRUTH_NOT_EXPR, type,
+ fold_build2 (code, type, arg0, arg1));
+}
- /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
- if (flag_unsafe_math_optimizations
- && (fcode == BUILT_IN_SQRT
- || fcode == BUILT_IN_SQRTF
- || fcode == BUILT_IN_SQRTL))
- {
- tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree narg1 = fold (build (MULT_EXPR, type, arg1,
- build_real (type, dconsthalf)));
+/* Used by constant folding to simplify calls to builtin functions. EXP is
+ the CALL_EXPR of a call to a builtin function. IGNORE is true if the
+ result of the function call is ignored. This function returns NULL_TREE
+ if no simplification was possible. */
- arglist = tree_cons (NULL_TREE, narg0,
- build_tree_list (NULL_TREE, narg1));
- return build_function_call_expr (fndecl, arglist);
- }
+static tree
+fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
+{
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ enum built_in_function fcode;
- /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
- if (flag_unsafe_math_optimizations
- && (fcode == BUILT_IN_POW
- || fcode == BUILT_IN_POWF
- || fcode == BUILT_IN_POWL))
- {
- tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
- tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
- tree narg1 = fold (build (MULT_EXPR, type, arg01, arg1));
- arglist = tree_cons (NULL_TREE, arg00,
- build_tree_list (NULL_TREE, narg1));
- return build_function_call_expr (fndecl, arglist);
- }
- }
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+ return targetm.fold_builtin (fndecl, arglist, ignore);
+
+ fcode = DECL_FUNCTION_CODE (fndecl);
+ switch (fcode)
+ {
+ case BUILT_IN_FPUTS:
+ return fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
+
+ case BUILT_IN_FPUTS_UNLOCKED:
+ return fold_builtin_fputs (arglist, ignore, true, NULL_TREE);
+
+ case BUILT_IN_STRSTR:
+ return fold_builtin_strstr (arglist, type);
+
+ case BUILT_IN_STRCAT:
+ return fold_builtin_strcat (arglist);
+
+ case BUILT_IN_STRNCAT:
+ return fold_builtin_strncat (arglist);
+
+ case BUILT_IN_STRSPN:
+ return fold_builtin_strspn (arglist);
+
+ case BUILT_IN_STRCSPN:
+ return fold_builtin_strcspn (arglist);
+
+ case BUILT_IN_STRCHR:
+ case BUILT_IN_INDEX:
+ return fold_builtin_strchr (arglist, type);
+
+ case BUILT_IN_STRRCHR:
+ case BUILT_IN_RINDEX:
+ return fold_builtin_strrchr (arglist, type);
+
+ case BUILT_IN_STRCPY:
+ return fold_builtin_strcpy (fndecl, arglist, NULL_TREE);
+
+ case BUILT_IN_STRNCPY:
+ return fold_builtin_strncpy (fndecl, arglist, NULL_TREE);
+
+ case BUILT_IN_STRCMP:
+ return fold_builtin_strcmp (arglist);
+
+ case BUILT_IN_STRNCMP:
+ return fold_builtin_strncmp (arglist);
+
+ case BUILT_IN_STRPBRK:
+ return fold_builtin_strpbrk (arglist, type);
+
+ case BUILT_IN_BCMP:
+ case BUILT_IN_MEMCMP:
+ return fold_builtin_memcmp (arglist);
+
+ case BUILT_IN_SPRINTF:
+ return fold_builtin_sprintf (arglist, ignore);
+
+ case BUILT_IN_CONSTANT_P:
+ {
+ tree val;
+
+ val = fold_builtin_constant_p (arglist);
+ /* Gimplification will pull the CALL_EXPR for the builtin out of
+ an if condition. When not optimizing, we'll not CSE it back.
+ To avoid link error types of regressions, return false now. */
+ if (!val && !optimize)
+ val = integer_zero_node;
+
+ return val;
+ }
+
+ case BUILT_IN_EXPECT:
+ return fold_builtin_expect (arglist);
+
+ case BUILT_IN_CLASSIFY_TYPE:
+ return fold_builtin_classify_type (arglist);
+
+ case BUILT_IN_STRLEN:
+ return fold_builtin_strlen (arglist);
+
+ CASE_FLT_FN (BUILT_IN_FABS):
+ return fold_builtin_fabs (arglist, type);
+
+ case BUILT_IN_ABS:
+ case BUILT_IN_LABS:
+ case BUILT_IN_LLABS:
+ case BUILT_IN_IMAXABS:
+ return fold_builtin_abs (arglist, type);
+
+ CASE_FLT_FN (BUILT_IN_CONJ):
+ if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
+ return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist));
+ break;
+
+ CASE_FLT_FN (BUILT_IN_CREAL):
+ if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
+ return non_lvalue (fold_build1 (REALPART_EXPR, type,
+ TREE_VALUE (arglist)));
break;
- case BUILT_IN_INF:
- case BUILT_IN_INFF:
- case BUILT_IN_INFL:
+ CASE_FLT_FN (BUILT_IN_CIMAG):
+ if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
+ return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
+ TREE_VALUE (arglist)));
+ break;
+
+ CASE_FLT_FN (BUILT_IN_CABS):
+ return fold_builtin_cabs (arglist, type, fndecl);
+
+ CASE_FLT_FN (BUILT_IN_SQRT):
+ return fold_builtin_sqrt (arglist, type);
+
+ CASE_FLT_FN (BUILT_IN_CBRT):
+ return fold_builtin_cbrt (arglist, type);
+
+ CASE_FLT_FN (BUILT_IN_SIN):
+ return fold_builtin_sin (arglist);
+
+ CASE_FLT_FN (BUILT_IN_COS):
+ return fold_builtin_cos (arglist, type, fndecl);
+
+ CASE_FLT_FN (BUILT_IN_EXP):
+ return fold_builtin_exponent (fndecl, arglist, &dconste);
+
+ CASE_FLT_FN (BUILT_IN_EXP2):
+ return fold_builtin_exponent (fndecl, arglist, &dconst2);
+
+ CASE_FLT_FN (BUILT_IN_EXP10):
+ CASE_FLT_FN (BUILT_IN_POW10):
+ return fold_builtin_exponent (fndecl, arglist, &dconst10);
+
+ CASE_FLT_FN (BUILT_IN_LOG):
+ return fold_builtin_logarithm (fndecl, arglist, &dconste);
+
+ CASE_FLT_FN (BUILT_IN_LOG2):
+ return fold_builtin_logarithm (fndecl, arglist, &dconst2);
+
+ CASE_FLT_FN (BUILT_IN_LOG10):
+ return fold_builtin_logarithm (fndecl, arglist, &dconst10);
+
+ CASE_FLT_FN (BUILT_IN_TAN):
+ return fold_builtin_tan (arglist);
+
+ CASE_FLT_FN (BUILT_IN_ATAN):
+ return fold_builtin_atan (arglist, type);
+
+ CASE_FLT_FN (BUILT_IN_POW):
+ return fold_builtin_pow (fndecl, arglist, type);
+
+ CASE_FLT_FN (BUILT_IN_POWI):
+ return fold_builtin_powi (fndecl, arglist, type);
+
+ CASE_FLT_FN (BUILT_IN_INF):
+ case BUILT_IN_INFD32:
+ case BUILT_IN_INFD64:
+ case BUILT_IN_INFD128:
return fold_builtin_inf (type, true);
- case BUILT_IN_HUGE_VAL:
- case BUILT_IN_HUGE_VALF:
- case BUILT_IN_HUGE_VALL:
+ CASE_FLT_FN (BUILT_IN_HUGE_VAL):
return fold_builtin_inf (type, false);
- case BUILT_IN_NAN:
- case BUILT_IN_NANF:
- case BUILT_IN_NANL:
+ CASE_FLT_FN (BUILT_IN_NAN):
+ case BUILT_IN_NAND32:
+ case BUILT_IN_NAND64:
+ case BUILT_IN_NAND128:
return fold_builtin_nan (arglist, type, true);
- case BUILT_IN_NANS:
- case BUILT_IN_NANSF:
- case BUILT_IN_NANSL:
+ CASE_FLT_FN (BUILT_IN_NANS):
return fold_builtin_nan (arglist, type, false);
- case BUILT_IN_FLOOR:
- case BUILT_IN_FLOORF:
- case BUILT_IN_FLOORL:
- return fold_builtin_floor (exp);
-
- case BUILT_IN_CEIL:
- case BUILT_IN_CEILF:
- case BUILT_IN_CEILL:
- return fold_builtin_ceil (exp);
-
- case BUILT_IN_TRUNC:
- case BUILT_IN_TRUNCF:
- case BUILT_IN_TRUNCL:
- return fold_builtin_trunc (exp);
-
- case BUILT_IN_ROUND:
- case BUILT_IN_ROUNDF:
- case BUILT_IN_ROUNDL:
- case BUILT_IN_NEARBYINT:
- case BUILT_IN_NEARBYINTF:
- case BUILT_IN_NEARBYINTL:
- return fold_trunc_transparent_mathfn (exp);
-
- case BUILT_IN_FFS:
- case BUILT_IN_FFSL:
- case BUILT_IN_FFSLL:
- case BUILT_IN_CLZ:
- case BUILT_IN_CLZL:
- case BUILT_IN_CLZLL:
- case BUILT_IN_CTZ:
- case BUILT_IN_CTZL:
- case BUILT_IN_CTZLL:
- case BUILT_IN_POPCOUNT:
- case BUILT_IN_POPCOUNTL:
- case BUILT_IN_POPCOUNTLL:
- case BUILT_IN_PARITY:
- case BUILT_IN_PARITYL:
- case BUILT_IN_PARITYLL:
- return fold_builtin_bitop (exp);
+ CASE_FLT_FN (BUILT_IN_FLOOR):
+ return fold_builtin_floor (fndecl, arglist);
+
+ CASE_FLT_FN (BUILT_IN_CEIL):
+ return fold_builtin_ceil (fndecl, arglist);
+
+ CASE_FLT_FN (BUILT_IN_TRUNC):
+ return fold_builtin_trunc (fndecl, arglist);
+
+ CASE_FLT_FN (BUILT_IN_ROUND):
+ return fold_builtin_round (fndecl, arglist);
+
+ CASE_FLT_FN (BUILT_IN_NEARBYINT):
+ CASE_FLT_FN (BUILT_IN_RINT):
+ return fold_trunc_transparent_mathfn (fndecl, arglist);
+
+ CASE_FLT_FN (BUILT_IN_LCEIL):
+ CASE_FLT_FN (BUILT_IN_LLCEIL):
+ CASE_FLT_FN (BUILT_IN_LFLOOR):
+ CASE_FLT_FN (BUILT_IN_LLFLOOR):
+ CASE_FLT_FN (BUILT_IN_LROUND):
+ CASE_FLT_FN (BUILT_IN_LLROUND):
+ return fold_builtin_int_roundingfn (fndecl, arglist);
+
+ CASE_FLT_FN (BUILT_IN_LRINT):
+ CASE_FLT_FN (BUILT_IN_LLRINT):
+ return fold_fixed_mathfn (fndecl, arglist);
+
+ CASE_INT_FN (BUILT_IN_FFS):
+ CASE_INT_FN (BUILT_IN_CLZ):
+ CASE_INT_FN (BUILT_IN_CTZ):
+ CASE_INT_FN (BUILT_IN_POPCOUNT):
+ CASE_INT_FN (BUILT_IN_PARITY):
+ return fold_builtin_bitop (fndecl, arglist);
+
+ case BUILT_IN_MEMSET:
+ return fold_builtin_memset (arglist, type, ignore);
case BUILT_IN_MEMCPY:
- return fold_builtin_memcpy (exp);
+ return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/0);
case BUILT_IN_MEMPCPY:
- return fold_builtin_mempcpy (exp);
+ return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/1);
case BUILT_IN_MEMMOVE:
- return fold_builtin_memmove (exp);
+ return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/3);
- case BUILT_IN_STRCPY:
- return fold_builtin_strcpy (exp);
+ case BUILT_IN_BZERO:
+ return fold_builtin_bzero (arglist, ignore);
- case BUILT_IN_STRNCPY:
- return fold_builtin_strncpy (exp);
+ case BUILT_IN_BCOPY:
+ return fold_builtin_bcopy (arglist, ignore);
+
+ CASE_FLT_FN (BUILT_IN_SIGNBIT):
+ return fold_builtin_signbit (fndecl, arglist);
+
+ case BUILT_IN_ISASCII:
+ return fold_builtin_isascii (arglist);
+
+ case BUILT_IN_TOASCII:
+ return fold_builtin_toascii (arglist);
+
+ case BUILT_IN_ISDIGIT:
+ return fold_builtin_isdigit (arglist);
+
+ CASE_FLT_FN (BUILT_IN_COPYSIGN):
+ return fold_builtin_copysign (fndecl, arglist, type);
+
+ CASE_FLT_FN (BUILT_IN_FINITE):
+ case BUILT_IN_FINITED32:
+ case BUILT_IN_FINITED64:
+ case BUILT_IN_FINITED128:
+ return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE);
+
+ CASE_FLT_FN (BUILT_IN_ISINF):
+ case BUILT_IN_ISINFD32:
+ case BUILT_IN_ISINFD64:
+ case BUILT_IN_ISINFD128:
+ return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF);
+
+ CASE_FLT_FN (BUILT_IN_ISNAN):
+ case BUILT_IN_ISNAND32:
+ case BUILT_IN_ISNAND64:
+ case BUILT_IN_ISNAND128:
+ return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN);
+
+ case BUILT_IN_ISGREATER:
+ return fold_builtin_unordered_cmp (fndecl, arglist, UNLE_EXPR, LE_EXPR);
+ case BUILT_IN_ISGREATEREQUAL:
+ return fold_builtin_unordered_cmp (fndecl, arglist, UNLT_EXPR, LT_EXPR);
+ case BUILT_IN_ISLESS:
+ return fold_builtin_unordered_cmp (fndecl, arglist, UNGE_EXPR, GE_EXPR);
+ case BUILT_IN_ISLESSEQUAL:
+ return fold_builtin_unordered_cmp (fndecl, arglist, UNGT_EXPR, GT_EXPR);
+ case BUILT_IN_ISLESSGREATER:
+ return fold_builtin_unordered_cmp (fndecl, arglist, UNEQ_EXPR, EQ_EXPR);
+ case BUILT_IN_ISUNORDERED:
+ return fold_builtin_unordered_cmp (fndecl, arglist, UNORDERED_EXPR,
+ NOP_EXPR);
+
+ /* We do the folding for va_start in the expander. */
+ case BUILT_IN_VA_START:
+ break;
- case BUILT_IN_MEMCMP:
- return fold_builtin_memcmp (exp);
+ case BUILT_IN_OBJECT_SIZE:
+ return fold_builtin_object_size (arglist);
+ case BUILT_IN_MEMCPY_CHK:
+ case BUILT_IN_MEMPCPY_CHK:
+ case BUILT_IN_MEMMOVE_CHK:
+ case BUILT_IN_MEMSET_CHK:
+ return fold_builtin_memory_chk (fndecl, arglist, NULL_TREE, ignore,
+ DECL_FUNCTION_CODE (fndecl));
+ case BUILT_IN_STRCPY_CHK:
+ case BUILT_IN_STPCPY_CHK:
+ return fold_builtin_stxcpy_chk (fndecl, arglist, NULL_TREE, ignore,
+ DECL_FUNCTION_CODE (fndecl));
+ case BUILT_IN_STRNCPY_CHK:
+ return fold_builtin_strncpy_chk (arglist, NULL_TREE);
+ case BUILT_IN_STRCAT_CHK:
+ return fold_builtin_strcat_chk (fndecl, arglist);
+ case BUILT_IN_STRNCAT_CHK:
+ return fold_builtin_strncat_chk (fndecl, arglist);
+ case BUILT_IN_SPRINTF_CHK:
+ case BUILT_IN_VSPRINTF_CHK:
+ return fold_builtin_sprintf_chk (arglist, DECL_FUNCTION_CODE (fndecl));
+ case BUILT_IN_SNPRINTF_CHK:
+ case BUILT_IN_VSNPRINTF_CHK:
+ return fold_builtin_snprintf_chk (arglist, NULL_TREE,
+ DECL_FUNCTION_CODE (fndecl));
- case BUILT_IN_STRCMP:
- return fold_builtin_strcmp (exp);
+ case BUILT_IN_PRINTF:
+ case BUILT_IN_PRINTF_UNLOCKED:
+ case BUILT_IN_VPRINTF:
+ case BUILT_IN_PRINTF_CHK:
+ case BUILT_IN_VPRINTF_CHK:
+ return fold_builtin_printf (fndecl, arglist, ignore,
+ DECL_FUNCTION_CODE (fndecl));
- case BUILT_IN_STRNCMP:
- return fold_builtin_strncmp (exp);
+ case BUILT_IN_FPRINTF:
+ case BUILT_IN_FPRINTF_UNLOCKED:
+ case BUILT_IN_VFPRINTF:
+ case BUILT_IN_FPRINTF_CHK:
+ case BUILT_IN_VFPRINTF_CHK:
+ return fold_builtin_fprintf (fndecl, arglist, ignore,
+ DECL_FUNCTION_CODE (fndecl));
default:
break;
@@ -6940,6 +9178,23 @@ fold_builtin (tree exp)
return 0;
}
+/* A wrapper function for builtin folding that prevents warnings for
+ "statement without effect" and the like, caused by removing the
+ call node earlier than the warning is generated. */
+
+tree
+fold_builtin (tree fndecl, tree arglist, bool ignore)
+{
+ tree exp = fold_builtin_1 (fndecl, arglist, ignore);
+ if (exp)
+ {
+ exp = build1 (NOP_EXPR, TREE_TYPE (exp), exp);
+ TREE_NO_WARNING (exp) = 1;
+ }
+
+ return exp;
+}
+
/* Conveniently construct a function call expression. */
tree
@@ -6948,9 +9203,8 @@ build_function_call_expr (tree fn, tree arglist)
tree call_expr;
call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
- call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
- call_expr, arglist);
- return fold (call_expr);
+ return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+ call_expr, arglist, NULL_TREE);
}
/* This function validates the types of a function call argument list
@@ -6985,8 +9239,14 @@ validate_arglist (tree arglist, ...)
/* If no parameters remain or the parameter's code does not
match the specified code, return false. Otherwise continue
checking any remaining arguments. */
- if (arglist == 0
- || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
+ if (arglist == 0)
+ goto end;
+ if (code == POINTER_TYPE)
+ {
+ if (! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))))
+ goto end;
+ }
+ else if (code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
goto end;
break;
}
@@ -7014,41 +9274,1927 @@ default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
return NULL_RTX;
}
-/* Instantiate all remaining CONSTANT_P_RTX nodes. */
+/* Returns true is EXP represents data that would potentially reside
+ in a readonly section. */
-void
-purge_builtin_constant_p (void)
+static bool
+readonly_data_expr (tree exp)
+{
+ STRIP_NOPS (exp);
+
+ if (TREE_CODE (exp) != ADDR_EXPR)
+ return false;
+
+ exp = get_base_address (TREE_OPERAND (exp, 0));
+ if (!exp)
+ return false;
+
+ /* Make sure we call decl_readonly_section only for trees it
+ can handle (since it returns true for everything it doesn't
+ understand). */
+ if (TREE_CODE (exp) == STRING_CST
+ || TREE_CODE (exp) == CONSTRUCTOR
+ || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
+ return decl_readonly_section (exp, 0);
+ else
+ return false;
+}
+
+/* Simplify a call to the strstr builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree.
+
+ The simplified form may be a constant or other expression which
+ computes the same value, but in a more efficient manner (including
+ calls to other builtin functions).
+
+ The call may contain arguments which need to be evaluated, but
+ which are not useful to determine the result of the call. In
+ this case we return a chain of COMPOUND_EXPRs. The LHS of each
+ COMPOUND_EXPR will be an argument which must be evaluated.
+ COMPOUND_EXPRs are chained through their RHS. The RHS of the last
+ COMPOUND_EXPR in the chain will contain the tree for the simplified
+ form of the builtin function call. */
+
+static tree
+fold_builtin_strstr (tree arglist, tree type)
+{
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree fn;
+ const char *p1, *p2;
+
+ p2 = c_getstr (s2);
+ if (p2 == NULL)
+ return 0;
+
+ p1 = c_getstr (s1);
+ if (p1 != NULL)
+ {
+ const char *r = strstr (p1, p2);
+ tree tem;
+
+ if (r == NULL)
+ return build_int_cst (TREE_TYPE (s1), 0);
+
+ /* Return an offset into the constant string argument. */
+ tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
+ s1, build_int_cst (TREE_TYPE (s1), r - p1));
+ return fold_convert (type, tem);
+ }
+
+ /* The argument is const char *, and the result is char *, so we need
+ a type conversion here to avoid a warning. */
+ if (p2[0] == '\0')
+ return fold_convert (type, s1);
+
+ if (p2[1] != '\0')
+ return 0;
+
+ fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+ if (!fn)
+ return 0;
+
+ /* New argument list transforming strstr(s1, s2) to
+ strchr(s1, s2[0]). */
+ arglist = build_tree_list (NULL_TREE,
+ build_int_cst (NULL_TREE, p2[0]));
+ arglist = tree_cons (NULL_TREE, s1, arglist);
+ return build_function_call_expr (fn, arglist);
+ }
+}
+
+/* Simplify a call to the strchr builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree.
+
+ The simplified form may be a constant or other expression which
+ computes the same value, but in a more efficient manner (including
+ calls to other builtin functions).
+
+ The call may contain arguments which need to be evaluated, but
+ which are not useful to determine the result of the call. In
+ this case we return a chain of COMPOUND_EXPRs. The LHS of each
+ COMPOUND_EXPR will be an argument which must be evaluated.
+ COMPOUND_EXPRs are chained through their RHS. The RHS of the last
+ COMPOUND_EXPR in the chain will contain the tree for the simplified
+ form of the builtin function call. */
+
+static tree
+fold_builtin_strchr (tree arglist, tree type)
+{
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
+ const char *p1;
+
+ if (TREE_CODE (s2) != INTEGER_CST)
+ return 0;
+
+ p1 = c_getstr (s1);
+ if (p1 != NULL)
+ {
+ char c;
+ const char *r;
+ tree tem;
+
+ if (target_char_cast (s2, &c))
+ return 0;
+
+ r = strchr (p1, c);
+
+ if (r == NULL)
+ return build_int_cst (TREE_TYPE (s1), 0);
+
+ /* Return an offset into the constant string argument. */
+ tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
+ s1, build_int_cst (TREE_TYPE (s1), r - p1));
+ return fold_convert (type, tem);
+ }
+ return 0;
+ }
+}
+
+/* Simplify a call to the strrchr builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree.
+
+ The simplified form may be a constant or other expression which
+ computes the same value, but in a more efficient manner (including
+ calls to other builtin functions).
+
+ The call may contain arguments which need to be evaluated, but
+ which are not useful to determine the result of the call. In
+ this case we return a chain of COMPOUND_EXPRs. The LHS of each
+ COMPOUND_EXPR will be an argument which must be evaluated.
+ COMPOUND_EXPRs are chained through their RHS. The RHS of the last
+ COMPOUND_EXPR in the chain will contain the tree for the simplified
+ form of the builtin function call. */
+
+static tree
+fold_builtin_strrchr (tree arglist, tree type)
+{
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree fn;
+ const char *p1;
+
+ if (TREE_CODE (s2) != INTEGER_CST)
+ return 0;
+
+ p1 = c_getstr (s1);
+ if (p1 != NULL)
+ {
+ char c;
+ const char *r;
+ tree tem;
+
+ if (target_char_cast (s2, &c))
+ return 0;
+
+ r = strrchr (p1, c);
+
+ if (r == NULL)
+ return build_int_cst (TREE_TYPE (s1), 0);
+
+ /* Return an offset into the constant string argument. */
+ tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
+ s1, build_int_cst (TREE_TYPE (s1), r - p1));
+ return fold_convert (type, tem);
+ }
+
+ if (! integer_zerop (s2))
+ return 0;
+
+ fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+ if (!fn)
+ return 0;
+
+ /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
+ return build_function_call_expr (fn, arglist);
+ }
+}
+
+/* Simplify a call to the strpbrk builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree.
+
+ The simplified form may be a constant or other expression which
+ computes the same value, but in a more efficient manner (including
+ calls to other builtin functions).
+
+ The call may contain arguments which need to be evaluated, but
+ which are not useful to determine the result of the call. In
+ this case we return a chain of COMPOUND_EXPRs. The LHS of each
+ COMPOUND_EXPR will be an argument which must be evaluated.
+ COMPOUND_EXPRs are chained through their RHS. The RHS of the last
+ COMPOUND_EXPR in the chain will contain the tree for the simplified
+ form of the builtin function call. */
+
+static tree
+fold_builtin_strpbrk (tree arglist, tree type)
+{
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree fn;
+ const char *p1, *p2;
+
+ p2 = c_getstr (s2);
+ if (p2 == NULL)
+ return 0;
+
+ p1 = c_getstr (s1);
+ if (p1 != NULL)
+ {
+ const char *r = strpbrk (p1, p2);
+ tree tem;
+
+ if (r == NULL)
+ return build_int_cst (TREE_TYPE (s1), 0);
+
+ /* Return an offset into the constant string argument. */
+ tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
+ s1, build_int_cst (TREE_TYPE (s1), r - p1));
+ return fold_convert (type, tem);
+ }
+
+ if (p2[0] == '\0')
+ /* strpbrk(x, "") == NULL.
+ Evaluate and ignore s1 in case it had side-effects. */
+ return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
+
+ if (p2[1] != '\0')
+ return 0; /* Really call strpbrk. */
+
+ fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+ if (!fn)
+ return 0;
+
+ /* New argument list transforming strpbrk(s1, s2) to
+ strchr(s1, s2[0]). */
+ arglist = build_tree_list (NULL_TREE,
+ build_int_cst (NULL_TREE, p2[0]));
+ arglist = tree_cons (NULL_TREE, s1, arglist);
+ return build_function_call_expr (fn, arglist);
+ }
+}
+
+/* Simplify a call to the strcat builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree.
+
+ The simplified form may be a constant or other expression which
+ computes the same value, but in a more efficient manner (including
+ calls to other builtin functions).
+
+ The call may contain arguments which need to be evaluated, but
+ which are not useful to determine the result of the call. In
+ this case we return a chain of COMPOUND_EXPRs. The LHS of each
+ COMPOUND_EXPR will be an argument which must be evaluated.
+ COMPOUND_EXPRs are chained through their RHS. The RHS of the last
+ COMPOUND_EXPR in the chain will contain the tree for the simplified
+ form of the builtin function call. */
+
+static tree
+fold_builtin_strcat (tree arglist)
+{
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree dst = TREE_VALUE (arglist),
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ const char *p = c_getstr (src);
+
+ /* If the string length is zero, return the dst parameter. */
+ if (p && *p == '\0')
+ return dst;
+
+ return 0;
+ }
+}
+
+/* Simplify a call to the strncat builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree.
+
+ The simplified form may be a constant or other expression which
+ computes the same value, but in a more efficient manner (including
+ calls to other builtin functions).
+
+ The call may contain arguments which need to be evaluated, but
+ which are not useful to determine the result of the call. In
+ this case we return a chain of COMPOUND_EXPRs. The LHS of each
+ COMPOUND_EXPR will be an argument which must be evaluated.
+ COMPOUND_EXPRs are chained through their RHS. The RHS of the last
+ COMPOUND_EXPR in the chain will contain the tree for the simplified
+ form of the builtin function call. */
+
+static tree
+fold_builtin_strncat (tree arglist)
+{
+ if (!validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree dst = TREE_VALUE (arglist);
+ tree src = TREE_VALUE (TREE_CHAIN (arglist));
+ tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ const char *p = c_getstr (src);
+
+ /* If the requested length is zero, or the src parameter string
+ length is zero, return the dst parameter. */
+ if (integer_zerop (len) || (p && *p == '\0'))
+ return omit_two_operands (TREE_TYPE (dst), dst, src, len);
+
+ /* If the requested len is greater than or equal to the string
+ length, call strcat. */
+ if (TREE_CODE (len) == INTEGER_CST && p
+ && compare_tree_int (len, strlen (p)) >= 0)
+ {
+ tree newarglist
+ = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
+ tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
+
+ /* If the replacement _DECL isn't initialized, don't do the
+ transformation. */
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, newarglist);
+ }
+ return 0;
+ }
+}
+
+/* Simplify a call to the strspn builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree.
+
+ The simplified form may be a constant or other expression which
+ computes the same value, but in a more efficient manner (including
+ calls to other builtin functions).
+
+ The call may contain arguments which need to be evaluated, but
+ which are not useful to determine the result of the call. In
+ this case we return a chain of COMPOUND_EXPRs. The LHS of each
+ COMPOUND_EXPR will be an argument which must be evaluated.
+ COMPOUND_EXPRs are chained through their RHS. The RHS of the last
+ COMPOUND_EXPR in the chain will contain the tree for the simplified
+ form of the builtin function call. */
+
+static tree
+fold_builtin_strspn (tree arglist)
+{
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
+ const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
+
+ /* If both arguments are constants, evaluate at compile-time. */
+ if (p1 && p2)
+ {
+ const size_t r = strspn (p1, p2);
+ return size_int (r);
+ }
+
+ /* If either argument is "", return 0. */
+ if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
+ /* Evaluate and ignore both arguments in case either one has
+ side-effects. */
+ return omit_two_operands (integer_type_node, integer_zero_node,
+ s1, s2);
+ return 0;
+ }
+}
+
+/* Simplify a call to the strcspn builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree.
+
+ The simplified form may be a constant or other expression which
+ computes the same value, but in a more efficient manner (including
+ calls to other builtin functions).
+
+ The call may contain arguments which need to be evaluated, but
+ which are not useful to determine the result of the call. In
+ this case we return a chain of COMPOUND_EXPRs. The LHS of each
+ COMPOUND_EXPR will be an argument which must be evaluated.
+ COMPOUND_EXPRs are chained through their RHS. The RHS of the last
+ COMPOUND_EXPR in the chain will contain the tree for the simplified
+ form of the builtin function call. */
+
+static tree
+fold_builtin_strcspn (tree arglist)
{
- rtx insn, set, arg, new, note;
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+ else
+ {
+ tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
+ const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
+
+ /* If both arguments are constants, evaluate at compile-time. */
+ if (p1 && p2)
+ {
+ const size_t r = strcspn (p1, p2);
+ return size_int (r);
+ }
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn)
- && (set = single_set (insn)) != NULL_RTX
- && (GET_CODE (arg = SET_SRC (set)) == CONSTANT_P_RTX
- || (GET_CODE (arg) == SUBREG
- && (GET_CODE (arg = SUBREG_REG (arg))
- == CONSTANT_P_RTX))))
+ /* If the first argument is "", return 0. */
+ if (p1 && *p1 == '\0')
+ {
+ /* Evaluate and ignore argument s2 in case it has
+ side-effects. */
+ return omit_one_operand (integer_type_node,
+ integer_zero_node, s2);
+ }
+
+ /* If the second argument is "", return __builtin_strlen(s1). */
+ if (p2 && *p2 == '\0')
+ {
+ tree newarglist = build_tree_list (NULL_TREE, s1),
+ fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+
+ /* If the replacement _DECL isn't initialized, don't do the
+ transformation. */
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, newarglist);
+ }
+ return 0;
+ }
+}
+
+/* Fold a call to the fputs builtin. IGNORE is true if the value returned
+ by the builtin will be ignored. UNLOCKED is true is true if this
+ actually a call to fputs_unlocked. If LEN in non-NULL, it represents
+ the known length of the string. Return NULL_TREE if no simplification
+ was possible. */
+
+tree
+fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
+{
+ tree fn;
+ /* If we're using an unlocked function, assume the other unlocked
+ functions exist explicitly. */
+ tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
+ : implicit_built_in_decls[BUILT_IN_FPUTC];
+ tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
+ : implicit_built_in_decls[BUILT_IN_FWRITE];
+
+ /* If the return value is used, don't do the transformation. */
+ if (!ignore)
+ return 0;
+
+ /* Verify the arguments in the original call. */
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+
+ if (! len)
+ len = c_strlen (TREE_VALUE (arglist), 0);
+
+ /* Get the length of the string passed to fputs. If the length
+ can't be determined, punt. */
+ if (!len
+ || TREE_CODE (len) != INTEGER_CST)
+ return 0;
+
+ switch (compare_tree_int (len, 1))
+ {
+ case -1: /* length is 0, delete the call entirely . */
+ return omit_one_operand (integer_type_node, integer_zero_node,
+ TREE_VALUE (TREE_CHAIN (arglist)));
+
+ case 0: /* length is 1, call fputc. */
+ {
+ const char *p = c_getstr (TREE_VALUE (arglist));
+
+ if (p != NULL)
+ {
+ /* New argument list transforming fputs(string, stream) to
+ fputc(string[0], stream). */
+ arglist = build_tree_list (NULL_TREE,
+ TREE_VALUE (TREE_CHAIN (arglist)));
+ arglist = tree_cons (NULL_TREE,
+ build_int_cst (NULL_TREE, p[0]),
+ arglist);
+ fn = fn_fputc;
+ break;
+ }
+ }
+ /* FALLTHROUGH */
+ case 1: /* length is greater than 1, call fwrite. */
{
- arg = XEXP (arg, 0);
- new = CONSTANT_P (arg) ? const1_rtx : const0_rtx;
- validate_change (insn, &SET_SRC (set), new, 0);
+ tree string_arg;
- /* Remove the REG_EQUAL note from the insn. */
- if ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
- remove_note (insn, note);
+ /* If optimizing for size keep fputs. */
+ if (optimize_size)
+ return 0;
+ string_arg = TREE_VALUE (arglist);
+ /* New argument list transforming fputs(string, stream) to
+ fwrite(string, 1, len, stream). */
+ arglist = build_tree_list (NULL_TREE,
+ TREE_VALUE (TREE_CHAIN (arglist)));
+ arglist = tree_cons (NULL_TREE, len, arglist);
+ arglist = tree_cons (NULL_TREE, size_one_node, arglist);
+ arglist = tree_cons (NULL_TREE, string_arg, arglist);
+ fn = fn_fwrite;
+ break;
}
+ default:
+ gcc_unreachable ();
+ }
+
+ /* If the replacement _DECL isn't initialized, don't do the
+ transformation. */
+ if (!fn)
+ return 0;
+
+ /* These optimizations are only performed when the result is ignored,
+ hence there's no need to cast the result to integer_type_node. */
+ return build_function_call_expr (fn, arglist);
}
-/* Returns true is EXP represents data that would potentially reside
- in a readonly section. */
+/* Fold the new_arg's arguments (ARGLIST). Returns true if there was an error
+ produced. False otherwise. This is done so that we don't output the error
+ or warning twice or three times. */
+bool
+fold_builtin_next_arg (tree arglist)
+{
+ tree fntype = TREE_TYPE (current_function_decl);
-static bool
-readonly_data_expr (tree exp)
+ if (TYPE_ARG_TYPES (fntype) == 0
+ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+ == void_type_node))
+ {
+ error ("%<va_start%> used in function with fixed args");
+ return true;
+ }
+ else if (!arglist)
+ {
+ /* Evidently an out of date version of <stdarg.h>; can't validate
+ va_start's second argument, but can still work as intended. */
+ warning (0, "%<__builtin_next_arg%> called without an argument");
+ return true;
+ }
+ /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
+ when we checked the arguments and if needed issued a warning. */
+ else if (!TREE_CHAIN (arglist)
+ || !integer_zerop (TREE_VALUE (arglist))
+ || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
+ || TREE_CHAIN (TREE_CHAIN (arglist)))
+ {
+ tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
+ tree arg = TREE_VALUE (arglist);
+
+ if (TREE_CHAIN (arglist))
+ {
+ error ("%<va_start%> used with too many arguments");
+ return true;
+ }
+
+ /* Strip off all nops for the sake of the comparison. This
+ is not quite the same as STRIP_NOPS. It does more.
+ We must also strip off INDIRECT_EXPR for C++ reference
+ parameters. */
+ while (TREE_CODE (arg) == NOP_EXPR
+ || TREE_CODE (arg) == CONVERT_EXPR
+ || TREE_CODE (arg) == NON_LVALUE_EXPR
+ || TREE_CODE (arg) == INDIRECT_REF)
+ arg = TREE_OPERAND (arg, 0);
+ if (arg != last_parm)
+ {
+ /* FIXME: Sometimes with the tree optimizers we can get the
+ not the last argument even though the user used the last
+ argument. We just warn and set the arg to be the last
+ argument so that we will get wrong-code because of
+ it. */
+ warning (0, "second parameter of %<va_start%> not last named argument");
+ }
+ /* We want to verify the second parameter just once before the tree
+ optimizers are run and then avoid keeping it in the tree,
+ as otherwise we could warn even for correct code like:
+ void foo (int i, ...)
+ { va_list ap; i++; va_start (ap, i); va_end (ap); } */
+ TREE_VALUE (arglist) = integer_zero_node;
+ TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
+ }
+ return false;
+}
+
+
+/* Simplify a call to the sprintf builtin.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree. If IGNORED is true, it means that
+ the caller does not use the returned value of the function. */
+
+static tree
+fold_builtin_sprintf (tree arglist, int ignored)
{
- STRIP_NOPS (exp);
+ tree call, retval, dest, fmt;
+ const char *fmt_str = NULL;
+
+ /* Verify the required arguments in the original call. We deal with two
+ types of sprintf() calls: 'sprintf (str, fmt)' and
+ 'sprintf (dest, "%s", orig)'. */
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
+ && !validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
+ VOID_TYPE))
+ return NULL_TREE;
- if (TREE_CODE (exp) == ADDR_EXPR)
- return decl_readonly_section (TREE_OPERAND (exp, 0), 0);
+ /* Get the destination string and the format specifier. */
+ dest = TREE_VALUE (arglist);
+ fmt = TREE_VALUE (TREE_CHAIN (arglist));
+ arglist = TREE_CHAIN (TREE_CHAIN (arglist));
+
+ /* Check whether the format is a literal string constant. */
+ fmt_str = c_getstr (fmt);
+ if (fmt_str == NULL)
+ return NULL_TREE;
+
+ call = NULL_TREE;
+ retval = NULL_TREE;
+
+ if (!init_target_chars())
+ return 0;
+
+ /* If the format doesn't contain % args or %%, use strcpy. */
+ if (strchr (fmt_str, target_percent) == NULL)
+ {
+ tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+
+ if (!fn)
+ return NULL_TREE;
+
+ /* Don't optimize sprintf (buf, "abc", ptr++). */
+ if (arglist)
+ return NULL_TREE;
+
+ /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
+ 'format' is known to contain no % formats. */
+ arglist = build_tree_list (NULL_TREE, fmt);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+ call = build_function_call_expr (fn, arglist);
+ if (!ignored)
+ retval = build_int_cst (NULL_TREE, strlen (fmt_str));
+ }
+
+ /* If the format is "%s", use strcpy if the result isn't used. */
+ else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
+ {
+ tree fn, orig;
+ fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+
+ if (!fn)
+ return NULL_TREE;
+
+ /* Don't crash on sprintf (str1, "%s"). */
+ if (!arglist)
+ return NULL_TREE;
+
+ /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
+ orig = TREE_VALUE (arglist);
+ arglist = build_tree_list (NULL_TREE, orig);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+ if (!ignored)
+ {
+ retval = c_strlen (orig, 1);
+ if (!retval || TREE_CODE (retval) != INTEGER_CST)
+ return NULL_TREE;
+ }
+ call = build_function_call_expr (fn, arglist);
+ }
+
+ if (call && retval)
+ {
+ retval = fold_convert
+ (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
+ retval);
+ return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
+ }
else
- return false;
+ return call;
+}
+
+/* Expand a call to __builtin_object_size. */
+
+rtx
+expand_builtin_object_size (tree exp)
+{
+ tree ost;
+ int object_size_type;
+ tree fndecl = get_callee_fndecl (exp);
+ tree arglist = TREE_OPERAND (exp, 1);
+ location_t locus = EXPR_LOCATION (exp);
+
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ {
+ error ("%Hfirst argument of %D must be a pointer, second integer constant",
+ &locus, fndecl);
+ expand_builtin_trap ();
+ return const0_rtx;
+ }
+
+ ost = TREE_VALUE (TREE_CHAIN (arglist));
+ STRIP_NOPS (ost);
+
+ if (TREE_CODE (ost) != INTEGER_CST
+ || tree_int_cst_sgn (ost) < 0
+ || compare_tree_int (ost, 3) > 0)
+ {
+ error ("%Hlast argument of %D is not integer constant between 0 and 3",
+ &locus, fndecl);
+ expand_builtin_trap ();
+ return const0_rtx;
+ }
+
+ object_size_type = tree_low_cst (ost, 0);
+
+ return object_size_type < 2 ? constm1_rtx : const0_rtx;
+}
+
+/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
+ FCODE is the BUILT_IN_* to use.
+ Return 0 if we failed; the caller should emit a normal call,
+ otherwise try to get the result in TARGET, if convenient (and in
+ mode MODE if that's convenient). */
+
+static rtx
+expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
+ enum built_in_function fcode)
+{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree dest, src, len, size;
+
+ if (!validate_arglist (arglist,
+ POINTER_TYPE,
+ fcode == BUILT_IN_MEMSET_CHK
+ ? INTEGER_TYPE : POINTER_TYPE,
+ INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ dest = TREE_VALUE (arglist);
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
+
+ if (! host_integerp (size, 1))
+ return 0;
+
+ if (host_integerp (len, 1) || integer_all_onesp (size))
+ {
+ tree fn;
+
+ if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
+ {
+ location_t locus = EXPR_LOCATION (exp);
+ warning (0, "%Hcall to %D will always overflow destination buffer",
+ &locus, get_callee_fndecl (exp));
+ return 0;
+ }
+
+ arglist = build_tree_list (NULL_TREE, len);
+ arglist = tree_cons (NULL_TREE, src, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+
+ fn = NULL_TREE;
+ /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
+ mem{cpy,pcpy,move,set} is available. */
+ switch (fcode)
+ {
+ case BUILT_IN_MEMCPY_CHK:
+ fn = built_in_decls[BUILT_IN_MEMCPY];
+ break;
+ case BUILT_IN_MEMPCPY_CHK:
+ fn = built_in_decls[BUILT_IN_MEMPCPY];
+ break;
+ case BUILT_IN_MEMMOVE_CHK:
+ fn = built_in_decls[BUILT_IN_MEMMOVE];
+ break;
+ case BUILT_IN_MEMSET_CHK:
+ fn = built_in_decls[BUILT_IN_MEMSET];
+ break;
+ default:
+ break;
+ }
+
+ if (! fn)
+ return 0;
+
+ fn = build_function_call_expr (fn, arglist);
+ if (TREE_CODE (fn) == CALL_EXPR)
+ CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+ return expand_expr (fn, target, mode, EXPAND_NORMAL);
+ }
+ else if (fcode == BUILT_IN_MEMSET_CHK)
+ return 0;
+ else
+ {
+ unsigned int dest_align
+ = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
+
+ /* If DEST is not a pointer type, call the normal function. */
+ if (dest_align == 0)
+ return 0;
+
+ /* If SRC and DEST are the same (and not volatile), do nothing. */
+ if (operand_equal_p (src, dest, 0))
+ {
+ tree expr;
+
+ if (fcode != BUILT_IN_MEMPCPY_CHK)
+ {
+ /* Evaluate and ignore LEN in case it has side-effects. */
+ expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return expand_expr (dest, target, mode, EXPAND_NORMAL);
+ }
+
+ len = fold_convert (TREE_TYPE (dest), len);
+ expr = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
+ return expand_expr (expr, target, mode, EXPAND_NORMAL);
+ }
+
+ /* __memmove_chk special case. */
+ if (fcode == BUILT_IN_MEMMOVE_CHK)
+ {
+ unsigned int src_align
+ = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
+
+ if (src_align == 0)
+ return 0;
+
+ /* If src is categorized for a readonly section we can use
+ normal __memcpy_chk. */
+ if (readonly_data_expr (src))
+ {
+ tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+ if (!fn)
+ return 0;
+ fn = build_function_call_expr (fn, arglist);
+ if (TREE_CODE (fn) == CALL_EXPR)
+ CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
+ return expand_expr (fn, target, mode, EXPAND_NORMAL);
+ }
+ }
+ return 0;
+ }
+}
+
+/* Emit warning if a buffer overflow is detected at compile time. */
+
+static void
+maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
+{
+ int arg_mask, is_strlen = 0;
+ tree arglist = TREE_OPERAND (exp, 1), a;
+ tree len, size;
+ location_t locus;
+
+ switch (fcode)
+ {
+ case BUILT_IN_STRCPY_CHK:
+ case BUILT_IN_STPCPY_CHK:
+ /* For __strcat_chk the warning will be emitted only if overflowing
+ by at least strlen (dest) + 1 bytes. */
+ case BUILT_IN_STRCAT_CHK:
+ arg_mask = 6;
+ is_strlen = 1;
+ break;
+ case BUILT_IN_STRNCPY_CHK:
+ arg_mask = 12;
+ break;
+ case BUILT_IN_SNPRINTF_CHK:
+ case BUILT_IN_VSNPRINTF_CHK:
+ arg_mask = 10;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ len = NULL_TREE;
+ size = NULL_TREE;
+ for (a = arglist; a && arg_mask; a = TREE_CHAIN (a), arg_mask >>= 1)
+ if (arg_mask & 1)
+ {
+ if (len)
+ size = a;
+ else
+ len = a;
+ }
+
+ if (!len || !size)
+ return;
+
+ len = TREE_VALUE (len);
+ size = TREE_VALUE (size);
+
+ if (! host_integerp (size, 1) || integer_all_onesp (size))
+ return;
+
+ if (is_strlen)
+ {
+ len = c_strlen (len, 1);
+ if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
+ return;
+ }
+ else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
+ return;
+
+ locus = EXPR_LOCATION (exp);
+ warning (0, "%Hcall to %D will always overflow destination buffer",
+ &locus, get_callee_fndecl (exp));
+}
+
+/* Emit warning if a buffer overflow is detected at compile time
+ in __sprintf_chk/__vsprintf_chk calls. */
+
+static void
+maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
+{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree dest, size, len, fmt, flag;
+ const char *fmt_str;
+
+ /* Verify the required arguments in the original call. */
+ if (! arglist)
+ return;
+ dest = TREE_VALUE (arglist);
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return;
+ flag = TREE_VALUE (arglist);
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return;
+ size = TREE_VALUE (arglist);
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return;
+ fmt = TREE_VALUE (arglist);
+ arglist = TREE_CHAIN (arglist);
+
+ if (! host_integerp (size, 1) || integer_all_onesp (size))
+ return;
+
+ /* Check whether the format is a literal string constant. */
+ fmt_str = c_getstr (fmt);
+ if (fmt_str == NULL)
+ return;
+
+ if (!init_target_chars())
+ return;
+
+ /* If the format doesn't contain % args or %%, we know its size. */
+ if (strchr (fmt_str, target_percent) == 0)
+ len = build_int_cstu (size_type_node, strlen (fmt_str));
+ /* If the format is "%s" and first ... argument is a string literal,
+ we know it too. */
+ else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
+ {
+ tree arg;
+
+ if (! arglist)
+ return;
+ arg = TREE_VALUE (arglist);
+ if (! POINTER_TYPE_P (TREE_TYPE (arg)))
+ return;
+
+ len = c_strlen (arg, 1);
+ if (!len || ! host_integerp (len, 1))
+ return;
+ }
+ else
+ return;
+
+ if (! tree_int_cst_lt (len, size))
+ {
+ location_t locus = EXPR_LOCATION (exp);
+ warning (0, "%Hcall to %D will always overflow destination buffer",
+ &locus, get_callee_fndecl (exp));
+ }
+}
+
+/* Fold a call to __builtin_object_size, if possible. */
+
+tree
+fold_builtin_object_size (tree arglist)
+{
+ tree ptr, ost, ret = 0;
+ int object_size_type;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ ptr = TREE_VALUE (arglist);
+ ost = TREE_VALUE (TREE_CHAIN (arglist));
+ STRIP_NOPS (ost);
+
+ if (TREE_CODE (ost) != INTEGER_CST
+ || tree_int_cst_sgn (ost) < 0
+ || compare_tree_int (ost, 3) > 0)
+ return 0;
+
+ object_size_type = tree_low_cst (ost, 0);
+
+ /* __builtin_object_size doesn't evaluate side-effects in its arguments;
+ if there are any side-effects, it returns (size_t) -1 for types 0 and 1
+ and (size_t) 0 for types 2 and 3. */
+ if (TREE_SIDE_EFFECTS (ptr))
+ return fold_convert (size_type_node,
+ object_size_type < 2
+ ? integer_minus_one_node : integer_zero_node);
+
+ if (TREE_CODE (ptr) == ADDR_EXPR)
+ ret = build_int_cstu (size_type_node,
+ compute_builtin_object_size (ptr, object_size_type));
+
+ else if (TREE_CODE (ptr) == SSA_NAME)
+ {
+ unsigned HOST_WIDE_INT bytes;
+
+ /* If object size is not known yet, delay folding until
+ later. Maybe subsequent passes will help determining
+ it. */
+ bytes = compute_builtin_object_size (ptr, object_size_type);
+ if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
+ ? -1 : 0))
+ ret = build_int_cstu (size_type_node, bytes);
+ }
+
+ if (ret)
+ {
+ ret = force_fit_type (ret, -1, false, false);
+ if (TREE_CONSTANT_OVERFLOW (ret))
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
+ IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
+ code of the builtin. If MAXLEN is not NULL, it is maximum length
+ passed as third argument. */
+
+tree
+fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
+ enum built_in_function fcode)
+{
+ tree dest, src, len, size, fn;
+
+ if (!validate_arglist (arglist,
+ POINTER_TYPE,
+ fcode == BUILT_IN_MEMSET_CHK
+ ? INTEGER_TYPE : POINTER_TYPE,
+ INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ dest = TREE_VALUE (arglist);
+ /* Actually val for __memset_chk, but it doesn't matter. */
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
+
+ /* If SRC and DEST are the same (and not volatile), return DEST
+ (resp. DEST+LEN for __mempcpy_chk). */
+ if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
+ {
+ if (fcode != BUILT_IN_MEMPCPY_CHK)
+ return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
+ else
+ {
+ tree temp = fold_convert (TREE_TYPE (dest), len);
+ temp = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp);
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
+ }
+ }
+
+ if (! host_integerp (size, 1))
+ return 0;
+
+ if (! integer_all_onesp (size))
+ {
+ if (! host_integerp (len, 1))
+ {
+ /* If LEN is not constant, try MAXLEN too.
+ For MAXLEN only allow optimizing into non-_ocs function
+ if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
+ if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+ {
+ if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
+ {
+ /* (void) __mempcpy_chk () can be optimized into
+ (void) __memcpy_chk (). */
+ fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+ }
+ return 0;
+ }
+ }
+ else
+ maxlen = len;
+
+ if (tree_int_cst_lt (size, maxlen))
+ return 0;
+ }
+
+ arglist = build_tree_list (NULL_TREE, len);
+ arglist = tree_cons (NULL_TREE, src, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+
+ fn = NULL_TREE;
+ /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
+ mem{cpy,pcpy,move,set} is available. */
+ switch (fcode)
+ {
+ case BUILT_IN_MEMCPY_CHK:
+ fn = built_in_decls[BUILT_IN_MEMCPY];
+ break;
+ case BUILT_IN_MEMPCPY_CHK:
+ fn = built_in_decls[BUILT_IN_MEMPCPY];
+ break;
+ case BUILT_IN_MEMMOVE_CHK:
+ fn = built_in_decls[BUILT_IN_MEMMOVE];
+ break;
+ case BUILT_IN_MEMSET_CHK:
+ fn = built_in_decls[BUILT_IN_MEMSET];
+ break;
+ default:
+ break;
+ }
+
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+}
+
+/* Fold a call to the __st[rp]cpy_chk builtin.
+ IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
+ code of the builtin. If MAXLEN is not NULL, it is maximum length of
+ strings passed as second argument. */
+
+tree
+fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
+ enum built_in_function fcode)
+{
+ tree dest, src, size, len, fn;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
+ VOID_TYPE))
+ return 0;
+
+ dest = TREE_VALUE (arglist);
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+
+ /* If SRC and DEST are the same (and not volatile), return DEST. */
+ if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
+
+ if (! host_integerp (size, 1))
+ return 0;
+
+ if (! integer_all_onesp (size))
+ {
+ len = c_strlen (src, 1);
+ if (! len || ! host_integerp (len, 1))
+ {
+ /* If LEN is not constant, try MAXLEN too.
+ For MAXLEN only allow optimizing into non-_ocs function
+ if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
+ if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+ {
+ if (fcode == BUILT_IN_STPCPY_CHK)
+ {
+ if (! ignore)
+ return 0;
+
+ /* If return value of __stpcpy_chk is ignored,
+ optimize into __strcpy_chk. */
+ fn = built_in_decls[BUILT_IN_STRCPY_CHK];
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+ }
+
+ if (! len || TREE_SIDE_EFFECTS (len))
+ return 0;
+
+ /* If c_strlen returned something, but not a constant,
+ transform __strcpy_chk into __memcpy_chk. */
+ fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+ if (!fn)
+ return 0;
+
+ len = size_binop (PLUS_EXPR, len, ssize_int (1));
+ arglist = build_tree_list (NULL_TREE, size);
+ arglist = tree_cons (NULL_TREE, len, arglist);
+ arglist = tree_cons (NULL_TREE, src, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
+ build_function_call_expr (fn, arglist));
+ }
+ }
+ else
+ maxlen = len;
+
+ if (! tree_int_cst_lt (maxlen, size))
+ return 0;
+ }
+
+ arglist = build_tree_list (NULL_TREE, src);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+
+ /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
+ fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
+ ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+}
+
+/* Fold a call to the __strncpy_chk builtin.
+ If MAXLEN is not NULL, it is maximum length passed as third argument. */
+
+tree
+fold_builtin_strncpy_chk (tree arglist, tree maxlen)
+{
+ tree dest, src, size, len, fn;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
+ INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ dest = TREE_VALUE (arglist);
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
+
+ if (! host_integerp (size, 1))
+ return 0;
+
+ if (! integer_all_onesp (size))
+ {
+ if (! host_integerp (len, 1))
+ {
+ /* If LEN is not constant, try MAXLEN too.
+ For MAXLEN only allow optimizing into non-_ocs function
+ if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
+ if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+ return 0;
+ }
+ else
+ maxlen = len;
+
+ if (tree_int_cst_lt (size, maxlen))
+ return 0;
+ }
+
+ arglist = build_tree_list (NULL_TREE, len);
+ arglist = tree_cons (NULL_TREE, src, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+
+ /* If __builtin_strncpy_chk is used, assume strncpy is available. */
+ fn = built_in_decls[BUILT_IN_STRNCPY];
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+}
+
+/* Fold a call to the __strcat_chk builtin FNDECL with ARGLIST. */
+
+static tree
+fold_builtin_strcat_chk (tree fndecl, tree arglist)
+{
+ tree dest, src, size, fn;
+ const char *p;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
+ VOID_TYPE))
+ return 0;
+
+ dest = TREE_VALUE (arglist);
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+
+ p = c_getstr (src);
+ /* If the SRC parameter is "", return DEST. */
+ if (p && *p == '\0')
+ return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
+
+ if (! host_integerp (size, 1) || ! integer_all_onesp (size))
+ return 0;
+
+ arglist = build_tree_list (NULL_TREE, src);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+
+ /* If __builtin_strcat_chk is used, assume strcat is available. */
+ fn = built_in_decls[BUILT_IN_STRCAT];
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+}
+
+/* Fold a call to the __strncat_chk builtin EXP. */
+
+static tree
+fold_builtin_strncat_chk (tree fndecl, tree arglist)
+{
+ tree dest, src, size, len, fn;
+ const char *p;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
+ INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ dest = TREE_VALUE (arglist);
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
+
+ p = c_getstr (src);
+ /* If the SRC parameter is "" or if LEN is 0, return DEST. */
+ if (p && *p == '\0')
+ return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
+ else if (integer_zerop (len))
+ return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
+
+ if (! host_integerp (size, 1))
+ return 0;
+
+ if (! integer_all_onesp (size))
+ {
+ tree src_len = c_strlen (src, 1);
+ if (src_len
+ && host_integerp (src_len, 1)
+ && host_integerp (len, 1)
+ && ! tree_int_cst_lt (len, src_len))
+ {
+ /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
+ fn = built_in_decls[BUILT_IN_STRCAT_CHK];
+ if (!fn)
+ return 0;
+
+ arglist = build_tree_list (NULL_TREE, size);
+ arglist = tree_cons (NULL_TREE, src, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+ return build_function_call_expr (fn, arglist);
+ }
+ return 0;
+ }
+
+ arglist = build_tree_list (NULL_TREE, len);
+ arglist = tree_cons (NULL_TREE, src, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+
+ /* If __builtin_strncat_chk is used, assume strncat is available. */
+ fn = built_in_decls[BUILT_IN_STRNCAT];
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+}
+
+/* Fold a call to __{,v}sprintf_chk with argument list ARGLIST. Return 0 if
+ a normal call should be emitted rather than expanding the function
+ inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
+
+static tree
+fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode)
+{
+ tree dest, size, len, fn, fmt, flag;
+ const char *fmt_str;
+
+ /* Verify the required arguments in the original call. */
+ if (! arglist)
+ return 0;
+ dest = TREE_VALUE (arglist);
+ if (! POINTER_TYPE_P (TREE_TYPE (dest)))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return 0;
+ flag = TREE_VALUE (arglist);
+ if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE)
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return 0;
+ size = TREE_VALUE (arglist);
+ if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return 0;
+ fmt = TREE_VALUE (arglist);
+ if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+
+ if (! host_integerp (size, 1))
+ return 0;
+
+ len = NULL_TREE;
+
+ if (!init_target_chars())
+ return 0;
+
+ /* Check whether the format is a literal string constant. */
+ fmt_str = c_getstr (fmt);
+ if (fmt_str != NULL)
+ {
+ /* If the format doesn't contain % args or %%, we know the size. */
+ if (strchr (fmt_str, target_percent) == 0)
+ {
+ if (fcode != BUILT_IN_SPRINTF_CHK || arglist == NULL_TREE)
+ len = build_int_cstu (size_type_node, strlen (fmt_str));
+ }
+ /* If the format is "%s" and first ... argument is a string literal,
+ we know the size too. */
+ else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
+ {
+ tree arg;
+
+ if (arglist && !TREE_CHAIN (arglist))
+ {
+ arg = TREE_VALUE (arglist);
+ if (POINTER_TYPE_P (TREE_TYPE (arg)))
+ {
+ len = c_strlen (arg, 1);
+ if (! len || ! host_integerp (len, 1))
+ len = NULL_TREE;
+ }
+ }
+ }
+ }
+
+ if (! integer_all_onesp (size))
+ {
+ if (! len || ! tree_int_cst_lt (len, size))
+ return 0;
+ }
+
+ /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
+ or if format doesn't contain % chars or is "%s". */
+ if (! integer_zerop (flag))
+ {
+ if (fmt_str == NULL)
+ return 0;
+ if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
+ return 0;
+ }
+
+ arglist = tree_cons (NULL_TREE, fmt, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+
+ /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
+ fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
+ ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+}
+
+/* Fold a call to {,v}snprintf with argument list ARGLIST. Return 0 if
+ a normal call should be emitted rather than expanding the function
+ inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
+ BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
+ passed as second argument. */
+
+tree
+fold_builtin_snprintf_chk (tree arglist, tree maxlen,
+ enum built_in_function fcode)
+{
+ tree dest, size, len, fn, fmt, flag;
+ const char *fmt_str;
+
+ /* Verify the required arguments in the original call. */
+ if (! arglist)
+ return 0;
+ dest = TREE_VALUE (arglist);
+ if (! POINTER_TYPE_P (TREE_TYPE (dest)))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return 0;
+ len = TREE_VALUE (arglist);
+ if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return 0;
+ flag = TREE_VALUE (arglist);
+ if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return 0;
+ size = TREE_VALUE (arglist);
+ if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ if (! arglist)
+ return 0;
+ fmt = TREE_VALUE (arglist);
+ if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+
+ if (! host_integerp (size, 1))
+ return 0;
+
+ if (! integer_all_onesp (size))
+ {
+ if (! host_integerp (len, 1))
+ {
+ /* If LEN is not constant, try MAXLEN too.
+ For MAXLEN only allow optimizing into non-_ocs function
+ if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
+ if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+ return 0;
+ }
+ else
+ maxlen = len;
+
+ if (tree_int_cst_lt (size, maxlen))
+ return 0;
+ }
+
+ if (!init_target_chars())
+ return 0;
+
+ /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
+ or if format doesn't contain % chars or is "%s". */
+ if (! integer_zerop (flag))
+ {
+ fmt_str = c_getstr (fmt);
+ if (fmt_str == NULL)
+ return 0;
+ if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
+ return 0;
+ }
+
+ arglist = tree_cons (NULL_TREE, fmt, arglist);
+ arglist = tree_cons (NULL_TREE, len, arglist);
+ arglist = tree_cons (NULL_TREE, dest, arglist);
+
+ /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
+ available. */
+ fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
+ ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
+ if (!fn)
+ return 0;
+
+ return build_function_call_expr (fn, arglist);
+}
+
+/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree. FCODE is the BUILT_IN_*
+ code of the function to be simplified. */
+
+static tree
+fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
+ enum built_in_function fcode)
+{
+ tree fmt, fn = NULL_TREE, fn_putchar, fn_puts, arg, call;
+ const char *fmt_str = NULL;
+
+ /* If the return value is used, don't do the transformation. */
+ if (! ignore)
+ return 0;
+
+ /* Verify the required arguments in the original call. */
+ if (fcode == BUILT_IN_PRINTF_CHK || fcode == BUILT_IN_VPRINTF_CHK)
+ {
+ tree flag;
+
+ if (! arglist)
+ return 0;
+ flag = TREE_VALUE (arglist);
+ if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
+ || TREE_SIDE_EFFECTS (flag))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ }
+
+ if (! arglist)
+ return 0;
+ fmt = TREE_VALUE (arglist);
+ if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+
+ /* Check whether the format is a literal string constant. */
+ fmt_str = c_getstr (fmt);
+ if (fmt_str == NULL)
+ return NULL_TREE;
+
+ if (fcode == BUILT_IN_PRINTF_UNLOCKED)
+ {
+ /* If we're using an unlocked function, assume the other
+ unlocked functions exist explicitly. */
+ fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
+ fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
+ }
+ else
+ {
+ fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
+ fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
+ }
+
+ if (!init_target_chars())
+ return 0;
+
+ if (strcmp (fmt_str, target_percent_s) == 0 || strchr (fmt_str, target_percent) == NULL)
+ {
+ const char *str;
+
+ if (strcmp (fmt_str, target_percent_s) == 0)
+ {
+ if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
+ return 0;
+
+ if (! arglist
+ || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
+ || TREE_CHAIN (arglist))
+ return 0;
+
+ str = c_getstr (TREE_VALUE (arglist));
+ if (str == NULL)
+ return 0;
+ }
+ else
+ {
+ /* The format specifier doesn't contain any '%' characters. */
+ if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
+ && arglist)
+ return 0;
+ str = fmt_str;
+ }
+
+ /* If the string was "", printf does nothing. */
+ if (str[0] == '\0')
+ return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
+
+ /* If the string has length of 1, call putchar. */
+ if (str[1] == '\0')
+ {
+ /* Given printf("c"), (where c is any one character,)
+ convert "c"[0] to an int and pass that to the replacement
+ function. */
+ arg = build_int_cst (NULL_TREE, str[0]);
+ arglist = build_tree_list (NULL_TREE, arg);
+ fn = fn_putchar;
+ }
+ else
+ {
+ /* If the string was "string\n", call puts("string"). */
+ size_t len = strlen (str);
+ if ((unsigned char)str[len - 1] == target_newline)
+ {
+ /* Create a NUL-terminated string that's one char shorter
+ than the original, stripping off the trailing '\n'. */
+ char *newstr = alloca (len);
+ memcpy (newstr, str, len - 1);
+ newstr[len - 1] = 0;
+
+ arg = build_string_literal (len, newstr);
+ arglist = build_tree_list (NULL_TREE, arg);
+ fn = fn_puts;
+ }
+ else
+ /* We'd like to arrange to call fputs(string,stdout) here,
+ but we need stdout and don't have a way to get it yet. */
+ return 0;
+ }
+ }
+
+ /* The other optimizations can be done only on the non-va_list variants. */
+ else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
+ return 0;
+
+ /* If the format specifier was "%s\n", call __builtin_puts(arg). */
+ else if (strcmp (fmt_str, target_percent_s_newline) == 0)
+ {
+ if (! arglist
+ || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
+ || TREE_CHAIN (arglist))
+ return 0;
+ fn = fn_puts;
+ }
+
+ /* If the format specifier was "%c", call __builtin_putchar(arg). */
+ else if (strcmp (fmt_str, target_percent_c) == 0)
+ {
+ if (! arglist
+ || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
+ || TREE_CHAIN (arglist))
+ return 0;
+ fn = fn_putchar;
+ }
+
+ if (!fn)
+ return 0;
+
+ call = build_function_call_expr (fn, arglist);
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
+}
+
+/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
+
+ Return 0 if no simplification was possible, otherwise return the
+ simplified form of the call as a tree. FCODE is the BUILT_IN_*
+ code of the function to be simplified. */
+
+static tree
+fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
+ enum built_in_function fcode)
+{
+ tree fp, fmt, fn = NULL_TREE, fn_fputc, fn_fputs, arg, call;
+ const char *fmt_str = NULL;
+
+ /* If the return value is used, don't do the transformation. */
+ if (! ignore)
+ return 0;
+
+ /* Verify the required arguments in the original call. */
+ if (! arglist)
+ return 0;
+ fp = TREE_VALUE (arglist);
+ if (! POINTER_TYPE_P (TREE_TYPE (fp)))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+
+ if (fcode == BUILT_IN_FPRINTF_CHK || fcode == BUILT_IN_VFPRINTF_CHK)
+ {
+ tree flag;
+
+ if (! arglist)
+ return 0;
+ flag = TREE_VALUE (arglist);
+ if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
+ || TREE_SIDE_EFFECTS (flag))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+ }
+
+ if (! arglist)
+ return 0;
+ fmt = TREE_VALUE (arglist);
+ if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
+ return 0;
+ arglist = TREE_CHAIN (arglist);
+
+ /* Check whether the format is a literal string constant. */
+ fmt_str = c_getstr (fmt);
+ if (fmt_str == NULL)
+ return NULL_TREE;
+
+ if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
+ {
+ /* If we're using an unlocked function, assume the other
+ unlocked functions exist explicitly. */
+ fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
+ fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
+ }
+ else
+ {
+ fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
+ fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
+ }
+
+ if (!init_target_chars())
+ return 0;
+
+ /* If the format doesn't contain % args or %%, use strcpy. */
+ if (strchr (fmt_str, target_percent) == NULL)
+ {
+ if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
+ && arglist)
+ return 0;
+
+ /* If the format specifier was "", fprintf does nothing. */
+ if (fmt_str[0] == '\0')
+ {
+ /* If FP has side-effects, just wait until gimplification is
+ done. */
+ if (TREE_SIDE_EFFECTS (fp))
+ return 0;
+
+ return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
+ }
+
+ /* When "string" doesn't contain %, replace all cases of
+ fprintf (fp, string) with fputs (string, fp). The fputs
+ builtin will take care of special cases like length == 1. */
+ arglist = build_tree_list (NULL_TREE, fp);
+ arglist = tree_cons (NULL_TREE, fmt, arglist);
+ fn = fn_fputs;
+ }
+
+ /* The other optimizations can be done only on the non-va_list variants. */
+ else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
+ return 0;
+
+ /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
+ else if (strcmp (fmt_str, target_percent_s) == 0)
+ {
+ if (! arglist
+ || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
+ || TREE_CHAIN (arglist))
+ return 0;
+ arg = TREE_VALUE (arglist);
+ arglist = build_tree_list (NULL_TREE, fp);
+ arglist = tree_cons (NULL_TREE, arg, arglist);
+ fn = fn_fputs;
+ }
+
+ /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
+ else if (strcmp (fmt_str, target_percent_c) == 0)
+ {
+ if (! arglist
+ || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
+ || TREE_CHAIN (arglist))
+ return 0;
+ arg = TREE_VALUE (arglist);
+ arglist = build_tree_list (NULL_TREE, fp);
+ arglist = tree_cons (NULL_TREE, arg, arglist);
+ fn = fn_fputc;
+ }
+
+ if (!fn)
+ return 0;
+
+ call = build_function_call_expr (fn, arglist);
+ return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
+}
+
+/* Initialize format string characters in the target charset. */
+
+static bool
+init_target_chars (void)
+{
+ static bool init;
+ if (!init)
+ {
+ target_newline = lang_hooks.to_target_charset ('\n');
+ target_percent = lang_hooks.to_target_charset ('%');
+ target_c = lang_hooks.to_target_charset ('c');
+ target_s = lang_hooks.to_target_charset ('s');
+ if (target_newline == 0 || target_percent == 0 || target_c == 0
+ || target_s == 0)
+ return false;
+
+ target_percent_c[0] = target_percent;
+ target_percent_c[1] = target_c;
+ target_percent_c[2] = '\0';
+
+ target_percent_s[0] = target_percent;
+ target_percent_s[1] = target_s;
+ target_percent_s[2] = '\0';
+
+ target_percent_s_newline[0] = target_percent;
+ target_percent_s_newline[1] = target_s;
+ target_percent_s_newline[2] = target_newline;
+ target_percent_s_newline[3] = '\0';
+
+ init = true;
+ }
+ return true;
}
diff --git a/contrib/gcc/c-common.c b/contrib/gcc/c-common.c
index 7305b3c6..b5ea608 100644
--- a/contrib/gcc/c-common.c
+++ b/contrib/gcc/c-common.c
@@ -1,6 +1,6 @@
/* Subroutines shared by all languages that are variants of C.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -42,6 +42,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree-inline.h"
#include "c-tree.h"
#include "toplev.h"
+#include "tree-iterator.h"
+#include "hashtab.h"
+#include "tree-mudflap.h"
+#include "opts.h"
+#include "real.h"
+#include "cgraph.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
@@ -55,6 +61,10 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */
#define SIZE_TYPE "long unsigned int"
#endif
+#ifndef PID_TYPE
+#define PID_TYPE "int"
+#endif
+
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
@@ -121,6 +131,10 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */
tree complex_double_type_node;
tree complex_long_double_type_node;
+ tree dfloat32_type_node;
+ tree dfloat64_type_node;
+ tree_dfloat128_type_node;
+
tree intQI_type_node;
tree intHI_type_node;
tree intSI_type_node;
@@ -182,11 +196,6 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */
*/
tree c_global_trees[CTI_MAX];
-
-/* TRUE if a code represents a statement. The front end init
- langhook should take care of initialization of this array. */
-
-bool statement_code_p[MAX_TREE_CODES];
/* Switches common to the C front ends. */
@@ -211,6 +220,10 @@ char flag_dump_macros;
char flag_dump_includes;
+/* Nonzero means process PCH files while preprocessing. */
+
+bool flag_pch_preprocess;
+
/* The file name to which we should write a precompiled header, or
NULL if no header will be written in this compile. */
@@ -248,78 +261,9 @@ int flag_ms_extensions;
int flag_no_asm;
-/* Nonzero means give string constants the type `const char *', as mandated
- by the standard. */
-
-int flag_const_strings;
-
/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */
int flag_signed_bitfields = 1;
-int explicit_flag_signed_bitfields;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-int warn_cast_qual;
-
-/* Warn about functions which might be candidates for format attributes. */
-
-int warn_missing_format_attribute;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
- of function pointers. */
-
-int warn_pointer_arith;
-
-/* Nonzero means do not warn that K&R style main() is not a function prototype. */
-
-int flag_bsd_no_warn_kr_main;
-
-/* Nonzero means warn for any global function def
- without separate previous prototype decl. */
-
-int warn_missing_prototypes;
-
-/* Warn if adding () is suggested. */
-
-int warn_parentheses;
-
-/* Warn if initializer is not completely bracketed. */
-
-int warn_missing_braces;
-
-/* Warn about comparison of signed and unsigned values.
- If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified
- (in which case -Wextra gets to decide). */
-
-int warn_sign_compare = -1;
-
-/* Nonzero means warn about usage of long long when `-pedantic'. */
-
-int warn_long_long = 1;
-
-/* Nonzero means warn about deprecated conversion from string constant to
- `char *'. */
-
-int warn_write_strings;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-int warn_redundant_decls;
-
-/* Warn about testing equality of floating point numbers. */
-
-int warn_float_equal;
-
-/* Warn about a subscript that has type char. */
-
-int warn_char_subscripts;
-
-/* Warn if a type conversion is done that might have confusing results. */
-
-int warn_conversion;
/* Warn about #pragma directives that are not recognized. */
@@ -330,35 +274,17 @@ int warn_unknown_pragmas; /* Tri state variable. */
int warn_format;
-/* Warn about Y2K problems with strftime formats. */
-
-int warn_format_y2k;
-
-/* Warn about excess arguments to formats. */
+/* Warn about using __null (as NULL in C++) as sentinel. For code compiled
+ with GCC this doesn't matter as __null is guaranteed to have the right
+ size. */
-int warn_format_extra_args;
-
-/* Warn about zero-length formats. */
-
-int warn_format_zero_length;
-
-/* Warn about non-literal format arguments. */
-
-int warn_format_nonliteral;
-
-/* Warn about possible security problems with calls to format functions. */
-
-int warn_format_security;
+int warn_strict_null_sentinel;
/* Zero means that faster, ...NonNil variants of objc_msgSend...
calls will be used in ObjC; passing nil receivers to such calls
will most likely result in crashes. */
int flag_nil_receivers = 1;
-/* Nonzero means that we will allow new ObjC exception syntax (@throw,
- @try, etc.) in source code. */
-int flag_objc_exceptions = 0;
-
/* Nonzero means that code generation will be altered to support
"zero-link" execution. This currently affects ObjC only, but may
affect other languages in the future. */
@@ -368,14 +294,9 @@ int flag_zero_link = 0;
unit. It will inform the ObjC runtime that class definition(s) herein
contained are to replace one(s) previously loaded. */
int flag_replace_objc_classes = 0;
-
-/* C/ObjC language option variables. */
+/* C/ObjC language option variables. */
-/* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error. */
-
-int mesg_implicit_function_declaration = -1;
/* Nonzero means allow type mismatches in conditional expressions;
just make their values `void'. */
@@ -390,75 +311,14 @@ int flag_isoc94;
int flag_isoc99;
-/* Nonzero means allow the BSD kernel printf enhancements. */
-
-int flag_bsd_format;
-
/* Nonzero means that we have builtin functions, and main is an int. */
int flag_hosted = 1;
-/* Nonzero means warn when casting a function call to a type that does
- not match the return type (e.g. (float)sqrt() or (anything*)malloc()
- when there is no previous declaration of sqrt or malloc. */
-
-int warn_bad_function_cast;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-int warn_traditional;
-
-/* Nonzero means warn for a declaration found after a statement. */
-
-int warn_declaration_after_statement;
-
-/* Nonzero means warn for non-prototype function decls
- or non-prototyped defs without previous prototype. */
-
-int warn_strict_prototypes;
-
-/* Nonzero means warn for any global function def
- without separate previous decl. */
-
-int warn_missing_declarations;
-
-/* Nonzero means warn about declarations of objects not at
- file-scope level and about *all* declarations of functions (whether
- or static) not at file-scope level. Note that we exclude
- implicit function declarations. To get warnings about those, use
- -Wimplicit. */
-
-int warn_nested_externs;
-
/* Warn if main is suspicious. */
int warn_main;
-/* Nonzero means warn about possible violations of sequence point rules. */
-
-int warn_sequence_point;
-
-/* Nonzero means warn about uninitialized variable when it is initialized with itself.
- For example: int i = i;, GCC will not warn about this when warn_init_self is nonzero. */
-
-int warn_init_self;
-
-/* Nonzero means to warn about compile-time division by zero. */
-int warn_div_by_zero = 1;
-
-/* Nonzero means warn about use of implicit int. */
-
-int warn_implicit_int;
-
-/* Warn about NULL being passed to argument slots marked as requiring
- non-NULL. */
-
-int warn_nonnull;
-
-/* Warn about old-style parameter declaration. */
-
-int warn_old_style_definition;
-
/* ObjC language option variables. */
@@ -468,43 +328,16 @@ int warn_old_style_definition;
int flag_gen_declaration;
-/* Generate code for GNU or NeXT runtime environment. */
-
-#ifdef NEXT_OBJC_RUNTIME
-int flag_next_runtime = 1;
-#else
-int flag_next_runtime = 0;
-#endif
-
/* Tells the compiler that this is a special run. Do not perform any
compiling, instead we are to test some platform dependent features
and output a C header file with appropriate definitions. */
int print_struct_values;
-/* ???. Undocumented. */
+/* Tells the compiler what is the constant string class for Objc. */
const char *constant_string_class_name;
-/* Warn if multiple methods are seen for the same selector, but with
- different argument types. Performs the check on the whole selector
- table at the end of compilation. */
-
-int warn_selector;
-
-/* Warn if a @selector() is found, and no method with that selector
- has been previously declared. The check is done on each
- @selector() as soon as it is found - so it warns about forward
- declarations. */
-
-int warn_undeclared_selector;
-
-/* Warn if methods required by a protocol are not implemented in the
- class adopting it. When turned off, methods inherited to that
- class are also considered implemented. */
-
-int warn_protocol = 1;
-
/* C++ language option variables. */
@@ -591,10 +424,16 @@ int flag_weak = 1;
int flag_working_directory = -1;
/* Nonzero to use __cxa_atexit, rather than atexit, to register
- destructors for local statics and global objects. */
+ destructors for local statics and global objects. '2' means it has been
+ set nonzero as a default, not by a command-line flag. */
int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
+/* Nonzero to use __cxa_get_exception_ptr in C++ exception-handling
+ code. '2' means it has not been set explicitly on the command line. */
+
+int flag_use_cxa_get_exception_ptr = 2;
+
/* Nonzero means make the default pedwarns warnings instead of errors.
The value of this flag is ignored if -pedantic is specified. */
@@ -607,70 +446,15 @@ int flag_permissive;
int flag_enforce_eh_specs = 1;
-/* Nonzero means warn about things that will change when compiling
- with an ABI-compliant compiler. */
-
-int warn_abi = 0;
+/* Nonzero means to generate thread-safe code for initializing local
+ statics. */
-/* Nonzero means warn about invalid uses of offsetof. */
-
-int warn_invalid_offsetof = 1;
+int flag_threadsafe_statics = 1;
/* Nonzero means warn about implicit declarations. */
int warn_implicit = 1;
-/* Nonzero means warn when all ctors or dtors are private, and the class
- has no friends. */
-
-int warn_ctor_dtor_privacy = 0;
-
-/* Nonzero means warn in function declared in derived class has the
- same name as a virtual in the base class, but fails to match the
- type signature of any virtual function in the base class. */
-
-int warn_overloaded_virtual;
-
-/* Nonzero means warn when declaring a class that has a non virtual
- destructor, when it really ought to have a virtual one. */
-
-int warn_nonvdtor;
-
-/* Nonzero means warn when the compiler will reorder code. */
-
-int warn_reorder;
-
-/* Nonzero means warn when synthesis behavior differs from Cfront's. */
-
-int warn_synth;
-
-/* Nonzero means warn when we convert a pointer to member function
- into a pointer to (void or function). */
-
-int warn_pmf2ptr = 1;
-
-/* Nonzero means warn about violation of some Effective C++ style rules. */
-
-int warn_ecpp;
-
-/* Nonzero means warn where overload resolution chooses a promotion from
- unsigned to signed over a conversion to an unsigned of the same size. */
-
-int warn_sign_promo;
-
-/* Nonzero means warn when an old-style cast is used. */
-
-int warn_old_style_cast;
-
-/* Nonzero means warn when non-templatized friend functions are
- declared within a template */
-
-int warn_nontemplate_friend = 1;
-
-/* Nonzero means complain about deprecated features. */
-
-int warn_deprecated = 1;
-
/* Maximum template instantiation depth. This limit is rather
arbitrary, but it exists to limit the time it takes to notice
infinite template instantiations. */
@@ -685,10 +469,6 @@ tree *ridpointers;
tree (*make_fname_decl) (tree, int);
-/* If non-NULL, the address of a language-specific function that takes
- any action required right before expand_function_end is called. */
-void (*lang_expand_function_end) (void);
-
/* Nonzero means the expression being parsed will never be evaluated.
This is a count, since unevaluated expressions can nest. */
int skip_evaluation;
@@ -715,27 +495,8 @@ const struct fname_var_t fname_vars[] =
};
static int constant_fits_type_p (tree, tree);
-
-/* Keep a stack of if statements. We record the number of compound
- statements seen up to the if keyword, as well as the line number
- and file of the if. If a potentially ambiguous else is seen, that
- fact is recorded; the warning is issued when we can be sure that
- the enclosing if statement does not have an else branch. */
-typedef struct
-{
- int compstmt_count;
- location_t locus;
- int needs_warning;
- tree if_stmt;
-} if_elt;
-
-static if_elt *if_stack;
-
-/* Amount of space in the if statement stack. */
-static int if_stack_space = 0;
-
-/* Stack pointer. */
-static int if_stack_pointer = 0;
+static tree check_case_value (tree);
+static bool check_case_bounds (tree, tree, tree *, tree *);
static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
@@ -744,8 +505,13 @@ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_always_inline_attribute (tree *, tree, tree, int,
bool *);
+static tree handle_gnu_inline_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
+static tree handle_externally_visible_attribute (tree *, tree, tree, int,
+ bool *);
static tree handle_const_attribute (tree *, tree, tree, int, bool *);
static tree handle_transparent_union_attribute (tree *, tree, tree,
int, bool *);
@@ -756,6 +522,7 @@ static tree handle_section_attribute (tree *, tree, tree, int, bool *);
static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
+static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ;
static tree handle_visibility_attribute (tree *, tree, tree, int,
bool *);
static tree handle_tls_model_attribute (tree *, tree, tree, int,
@@ -763,9 +530,11 @@ static tree handle_tls_model_attribute (tree *, tree, tree, int,
static tree handle_no_instrument_function_attribute (tree *, tree,
tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
bool *);
static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
static tree handle_deprecated_attribute (tree *, tree, tree, int,
bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int,
@@ -775,6 +544,7 @@ static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
bool *);
+static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static void check_function_nonnull (tree, tree);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -805,10 +575,16 @@ const struct attribute_spec c_common_attribute_table[] =
handle_noinline_attribute },
{ "always_inline", 0, 0, true, false, false,
handle_always_inline_attribute },
+ { "gnu_inline", 0, 0, true, false, false,
+ handle_gnu_inline_attribute },
+ { "flatten", 0, 0, true, false, false,
+ handle_flatten_attribute },
{ "used", 0, 0, true, false, false,
handle_used_attribute },
{ "unused", 0, 0, false, false, false,
handle_unused_attribute },
+ { "externally_visible", 0, 0, true, false, false,
+ handle_externally_visible_attribute },
/* The same comments as for noreturn attributes apply to const ones. */
{ "const", 0, 0, true, false, false,
handle_const_attribute },
@@ -828,19 +604,27 @@ const struct attribute_spec c_common_attribute_table[] =
handle_weak_attribute },
{ "alias", 1, 1, true, false, false,
handle_alias_attribute },
+ { "weakref", 0, 1, true, false, false,
+ handle_weakref_attribute },
{ "no_instrument_function", 0, 0, true, false, false,
handle_no_instrument_function_attribute },
{ "malloc", 0, 0, true, false, false,
handle_malloc_attribute },
+ { "returns_twice", 0, 0, true, false, false,
+ handle_returns_twice_attribute },
{ "no_stack_limit", 0, 0, true, false, false,
handle_no_limit_stack_attribute },
{ "pure", 0, 0, true, false, false,
handle_pure_attribute },
+ /* For internal use (marking of builtins) only. The name contains space
+ to prevent its usage in source code. */
+ { "no vops", 0, 0, true, false, false,
+ handle_novops_attribute },
{ "deprecated", 0, 0, false, false, false,
handle_deprecated_attribute },
{ "vector_size", 1, 1, false, true, false,
handle_vector_size_attribute },
- { "visibility", 1, 1, true, false, false,
+ { "visibility", 1, 1, false, false, false,
handle_visibility_attribute },
{ "tls_model", 1, 1, true, false, false,
handle_tls_model_attribute },
@@ -853,6 +637,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_cleanup_attribute },
{ "warn_unused_result", 0, 0, false, true, true,
handle_warn_unused_result_attribute },
+ { "sentinel", 0, 1, false, true, true,
+ handle_sentinel_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -869,131 +655,6 @@ const struct attribute_spec c_common_format_attribute_table[] =
{ NULL, 0, 0, false, false, false, NULL }
};
-/* Record the start of an if-then, and record the start of it
- for ambiguous else detection.
-
- COND is the condition for the if-then statement.
-
- IF_STMT is the statement node that has already been created for
- this if-then statement. It is created before parsing the
- condition to keep line number information accurate. */
-
-void
-c_expand_start_cond (tree cond, int compstmt_count, tree if_stmt)
-{
- /* Make sure there is enough space on the stack. */
- if (if_stack_space == 0)
- {
- if_stack_space = 10;
- if_stack = xmalloc (10 * sizeof (if_elt));
- }
- else if (if_stack_space == if_stack_pointer)
- {
- if_stack_space += 10;
- if_stack = xrealloc (if_stack, if_stack_space * sizeof (if_elt));
- }
-
- IF_COND (if_stmt) = cond;
- add_stmt (if_stmt);
-
- /* Record this if statement. */
- if_stack[if_stack_pointer].compstmt_count = compstmt_count;
- if_stack[if_stack_pointer].locus = input_location;
- if_stack[if_stack_pointer].needs_warning = 0;
- if_stack[if_stack_pointer].if_stmt = if_stmt;
- if_stack_pointer++;
-}
-
-/* Called after the then-clause for an if-statement is processed. */
-
-void
-c_finish_then (void)
-{
- tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
- RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
-}
-
-/* Record the end of an if-then. Optionally warn if a nested
- if statement had an ambiguous else clause. */
-
-void
-c_expand_end_cond (void)
-{
- if_stack_pointer--;
- if (if_stack[if_stack_pointer].needs_warning)
- warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
- &if_stack[if_stack_pointer].locus);
- last_expr_type = NULL_TREE;
-}
-
-/* Called between the then-clause and the else-clause
- of an if-then-else. */
-
-void
-c_expand_start_else (void)
-{
- /* An ambiguous else warning must be generated for the enclosing if
- statement, unless we see an else branch for that one, too. */
- if (warn_parentheses
- && if_stack_pointer > 1
- && (if_stack[if_stack_pointer - 1].compstmt_count
- == if_stack[if_stack_pointer - 2].compstmt_count))
- if_stack[if_stack_pointer - 2].needs_warning = 1;
-
- /* Even if a nested if statement had an else branch, it can't be
- ambiguous if this one also has an else. So don't warn in that
- case. Also don't warn for any if statements nested in this else. */
- if_stack[if_stack_pointer - 1].needs_warning = 0;
- if_stack[if_stack_pointer - 1].compstmt_count--;
-}
-
-/* Called after the else-clause for an if-statement is processed. */
-
-void
-c_finish_else (void)
-{
- tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
- RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
-}
-
-/* Begin an if-statement. Returns a newly created IF_STMT if
- appropriate.
-
- Unlike the C++ front-end, we do not call add_stmt here; it is
- probably safe to do so, but I am not very familiar with this
- code so I am being extra careful not to change its behavior
- beyond what is strictly necessary for correctness. */
-
-tree
-c_begin_if_stmt (void)
-{
- tree r;
- r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
- return r;
-}
-
-/* Begin a while statement. Returns a newly created WHILE_STMT if
- appropriate.
-
- Unlike the C++ front-end, we do not call add_stmt here; it is
- probably safe to do so, but I am not very familiar with this
- code so I am being extra careful not to change its behavior
- beyond what is strictly necessary for correctness. */
-
-tree
-c_begin_while_stmt (void)
-{
- tree r;
- r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
- return r;
-}
-
-void
-c_finish_while_stmt_cond (tree cond, tree while_stmt)
-{
- WHILE_COND (while_stmt) = cond;
-}
-
/* Push current bindings for the function name VAR_DECLS. */
void
@@ -1008,7 +669,7 @@ start_fname_decls (void)
if (decl)
{
- saved = tree_cons (decl, build_int_2 (ix, 0), saved);
+ saved = tree_cons (decl, build_int_cst (NULL_TREE, ix), saved);
*fname_vars[ix].decl = NULL_TREE;
}
}
@@ -1019,43 +680,30 @@ start_fname_decls (void)
saved_function_name_decls);
}
-/* Finish up the current bindings, adding them into the
- current function's statement tree. This is done by wrapping the
- function's body in a COMPOUND_STMT containing these decls too. This
- must be done _before_ finish_stmt_tree is called. If there is no
- current function, we must be at file scope and no statements are
- involved. Pop the previous bindings. */
+/* Finish up the current bindings, adding them into the current function's
+ statement tree. This must be done _before_ finish_stmt_tree is called.
+ If there is no current function, we must be at file scope and no statements
+ are involved. Pop the previous bindings. */
void
finish_fname_decls (void)
{
unsigned ix;
- tree body = NULL_TREE;
+ tree stmts = NULL_TREE;
tree stack = saved_function_name_decls;
for (; stack && TREE_VALUE (stack); stack = TREE_CHAIN (stack))
- body = chainon (TREE_VALUE (stack), body);
+ append_to_statement_list (TREE_VALUE (stack), &stmts);
- if (body)
+ if (stmts)
{
- /* They were called into existence, so add to statement tree. Add
- the DECL_STMTs inside the outermost scope. */
- tree *p = &DECL_SAVED_TREE (current_function_decl);
- /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK. */
- while (TREE_CODE (*p) != COMPOUND_STMT)
- {
- if (TREE_CODE (*p) == EXPR_STMT)
- p = &TREE_CHAIN (*p);
- else
- p = &TREE_OPERAND(*p, 0);
- }
+ tree *bodyp = &DECL_SAVED_TREE (current_function_decl);
- p = &COMPOUND_BODY (*p);
- if (TREE_CODE (*p) == SCOPE_STMT)
- p = &TREE_CHAIN (*p);
+ if (TREE_CODE (*bodyp) == BIND_EXPR)
+ bodyp = &BIND_EXPR_BODY (*bodyp);
- body = chainon (body, *p);
- *p = body;
+ append_to_statement_list_force (*bodyp, &stmts);
+ *bodyp = stmts;
}
for (ix = 0; fname_vars[ix].decl; ix++)
@@ -1079,26 +727,68 @@ finish_fname_decls (void)
}
/* Return the text name of the current function, suitably prettified
- by PRETTY_P. */
+ by PRETTY_P. Return string must be freed by caller. */
const char *
fname_as_string (int pretty_p)
{
const char *name = "top level";
+ char *namep;
int vrb = 2;
- if (! pretty_p)
+ if (!pretty_p)
{
name = "";
vrb = 0;
}
if (current_function_decl)
- name = (*lang_hooks.decl_printable_name) (current_function_decl, vrb);
+ name = lang_hooks.decl_printable_name (current_function_decl, vrb);
+
+ if (c_lex_string_translate)
+ {
+ int len = strlen (name) + 3; /* Two for '"'s. One for NULL. */
+ cpp_string cstr = { 0, 0 }, strname;
+
+ namep = XNEWVEC (char, len);
+ snprintf (namep, len, "\"%s\"", name);
+ strname.text = (unsigned char *) namep;
+ strname.len = len - 1;
+
+ if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false))
+ {
+ XDELETEVEC (namep);
+ return (char *) cstr.text;
+ }
+ }
+ else
+ namep = xstrdup (name);
- return name;
+ return namep;
}
+/* Expand DECL if it declares an entity not handled by the
+ common code. */
+
+int
+c_expand_decl (tree decl)
+{
+ if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+ {
+ /* Let the back-end know about this variable. */
+ if (!anon_aggr_type_p (TREE_TYPE (decl)))
+ emit_local_var (decl);
+ else
+ expand_anon_union_decl (decl, NULL_TREE,
+ DECL_ANON_UNION_ELEMS (decl));
+ }
+ else
+ return 0;
+
+ return 1;
+}
+
+
/* Return the VAR_DECL for a const char array naming the current
function. If the VAR_DECL has not yet been created, create it
now. RID indicates how it should be formatted and IDENTIFIER_NODE
@@ -1119,33 +809,30 @@ fname_decl (unsigned int rid, tree id)
decl = *fname_vars[ix].decl;
if (!decl)
{
- tree saved_last_tree = last_tree;
/* If a tree is built here, it would normally have the lineno of
the current statement. Later this tree will be moved to the
beginning of the function and this line number will be wrong.
To avoid this problem set the lineno to 0 here; that prevents
it from appearing in the RTL. */
- int saved_lineno = input_line;
+ tree stmts;
+ location_t saved_location = input_location;
+#ifdef USE_MAPPED_LOCATION
+ input_location = UNKNOWN_LOCATION;
+#else
input_line = 0;
+#endif
+ stmts = push_stmt_list ();
decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
- if (last_tree != saved_last_tree)
- {
- /* We created some statement tree for the decl. This belongs
- at the start of the function, so remove it now and reinsert
- it after the function is complete. */
- tree stmts = TREE_CHAIN (saved_last_tree);
-
- TREE_CHAIN (saved_last_tree) = NULL_TREE;
- last_tree = saved_last_tree;
- saved_function_name_decls = tree_cons (decl, stmts,
- saved_function_name_decls);
- }
+ stmts = pop_stmt_list (stmts);
+ if (!IS_EMPTY_STMT (stmts))
+ saved_function_name_decls
+ = tree_cons (decl, stmts, saved_function_name_decls);
*fname_vars[ix].decl = decl;
- input_line = saved_lineno;
+ input_location = saved_location;
}
if (!ix && !current_function_decl)
- pedwarn ("'%D' is not defined outside of function scope", decl);
+ pedwarn ("%qD is not defined outside of function scope", decl);
return decl;
}
@@ -1157,37 +844,56 @@ fix_string_type (tree value)
{
const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
const int wide_flag = TREE_TYPE (value) == wchar_array_type_node;
- const int nchars_max = flag_isoc99 ? 4095 : 509;
int length = TREE_STRING_LENGTH (value);
int nchars;
+ tree e_type, i_type, a_type;
/* Compute the number of elements, for the array type. */
nchars = wide_flag ? length / wchar_bytes : length;
- if (pedantic && nchars - 1 > nchars_max && !c_dialect_cxx ())
- pedwarn ("string length `%d' is greater than the length `%d' ISO C%d compilers are required to support",
- nchars - 1, nchars_max, flag_isoc99 ? 99 : 89);
-
- /* Create the array type for the string constant.
- -Wwrite-strings says make the string constant an array of const char
- so that copying it to a non-const pointer will get a warning.
- For C++, this is the standard behavior. */
- if (flag_const_strings && ! flag_writable_strings)
- {
- tree elements
- = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
- 1, 0);
- TREE_TYPE (value)
- = build_array_type (elements,
- build_index_type (build_int_2 (nchars - 1, 0)));
- }
- else
- TREE_TYPE (value)
- = build_array_type (wide_flag ? wchar_type_node : char_type_node,
- build_index_type (build_int_2 (nchars - 1, 0)));
-
+ /* C89 2.2.4.1, C99 5.2.4.1 (Translation limits). The analogous
+ limit in C++98 Annex B is very large (65536) and is not normative,
+ so we do not diagnose it (warn_overlength_strings is forced off
+ in c_common_post_options). */
+ if (warn_overlength_strings)
+ {
+ const int nchars_max = flag_isoc99 ? 4095 : 509;
+ const int relevant_std = flag_isoc99 ? 99 : 90;
+ if (nchars - 1 > nchars_max)
+ /* Translators: The %d after 'ISO C' will be 90 or 99. Do not
+ separate the %d from the 'C'. 'ISO' should not be
+ translated, but it may be moved after 'C%d' in languages
+ where modifiers follow nouns. */
+ pedwarn ("string length %qd is greater than the length %qd "
+ "ISO C%d compilers are required to support",
+ nchars - 1, nchars_max, relevant_std);
+ }
+
+ /* Create the array type for the string constant. The ISO C++
+ standard says that a string literal has type `const char[N]' or
+ `const wchar_t[N]'. We use the same logic when invoked as a C
+ front-end with -Wwrite-strings.
+ ??? We should change the type of an expression depending on the
+ state of a warning flag. We should just be warning -- see how
+ this is handled in the C++ front-end for the deprecated implicit
+ conversion from string literals to `char*' or `wchar_t*'.
+
+ The C++ front end relies on TYPE_MAIN_VARIANT of a cv-qualified
+ array type being the unqualified version of that type.
+ Therefore, if we are constructing an array of const char, we must
+ construct the matching unqualified array type first. The C front
+ end does not require this, but it does no harm, so we do it
+ unconditionally. */
+ e_type = wide_flag ? wchar_type_node : char_type_node;
+ i_type = build_index_type (build_int_cst (NULL_TREE, nchars - 1));
+ a_type = build_array_type (e_type, i_type);
+ if (c_dialect_cxx() || warn_write_strings)
+ a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
+
+ TREE_TYPE (value) = a_type;
TREE_CONSTANT (value) = 1;
- TREE_READONLY (value) = ! flag_writable_strings;
+ TREE_INVARIANT (value) = 1;
+ TREE_READONLY (value) = 1;
TREE_STATIC (value) = 1;
return value;
}
@@ -1204,7 +910,9 @@ constant_expression_warning (tree value)
if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
|| TREE_CODE (value) == VECTOR_CST
|| TREE_CODE (value) == COMPLEX_CST)
- && TREE_CONSTANT_OVERFLOW (value) && pedantic)
+ && TREE_CONSTANT_OVERFLOW (value)
+ && warn_overflow
+ && pedantic)
pedwarn ("overflow in constant expression");
}
@@ -1225,7 +933,7 @@ overflow_warning (tree value)
{
TREE_OVERFLOW (value) = 0;
if (skip_evaluation == 0)
- warning ("integer overflow in expression");
+ warning (OPT_Woverflow, "integer overflow in expression");
}
else if ((TREE_CODE (value) == REAL_CST
|| (TREE_CODE (value) == COMPLEX_CST
@@ -1234,13 +942,13 @@ overflow_warning (tree value)
{
TREE_OVERFLOW (value) = 0;
if (skip_evaluation == 0)
- warning ("floating point overflow in expression");
+ warning (OPT_Woverflow, "floating point overflow in expression");
}
else if (TREE_CODE (value) == VECTOR_CST && TREE_OVERFLOW (value))
{
TREE_OVERFLOW (value) = 0;
if (skip_evaluation == 0)
- warning ("vector overflow in expression");
+ warning (OPT_Woverflow, "vector overflow in expression");
}
}
@@ -1249,25 +957,93 @@ overflow_warning (tree value)
Invoke this function on every expression that might be implicitly
converted to an unsigned type. */
-void
+static void
unsigned_conversion_warning (tree result, tree operand)
{
tree type = TREE_TYPE (result);
if (TREE_CODE (operand) == INTEGER_CST
&& TREE_CODE (type) == INTEGER_TYPE
- && TREE_UNSIGNED (type)
+ && TYPE_UNSIGNED (type)
&& skip_evaluation == 0
&& !int_fits_type_p (operand, type))
{
if (!int_fits_type_p (operand, c_common_signed_type (type)))
/* This detects cases like converting -129 or 256 to unsigned char. */
- warning ("large integer implicitly truncated to unsigned type");
- else if (warn_conversion)
- warning ("negative integer implicitly converted to unsigned type");
+ warning (OPT_Woverflow,
+ "large integer implicitly truncated to unsigned type");
+ else
+ warning (OPT_Wconversion,
+ "negative integer implicitly converted to unsigned type");
}
}
+/* Print a warning about casts that might indicate violation
+ of strict aliasing rules if -Wstrict-aliasing is used and
+ strict aliasing mode is in effect. OTYPE is the original
+ TREE_TYPE of EXPR, and TYPE the type we're casting to. */
+
+void
+strict_aliasing_warning (tree otype, tree type, tree expr)
+{
+ if (flag_strict_aliasing && warn_strict_aliasing
+ && POINTER_TYPE_P (type) && POINTER_TYPE_P (otype)
+ && TREE_CODE (expr) == ADDR_EXPR
+ && (DECL_P (TREE_OPERAND (expr, 0))
+ || handled_component_p (TREE_OPERAND (expr, 0)))
+ && !VOID_TYPE_P (TREE_TYPE (type)))
+ {
+ /* Casting the address of an object to non void pointer. Warn
+ if the cast breaks type based aliasing. */
+ if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
+ warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
+ "might break strict-aliasing rules");
+ else
+ {
+ HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+
+ if (!alias_sets_conflict_p (set1, set2))
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer will break strict-aliasing rules");
+ else if (warn_strict_aliasing > 1
+ && !alias_sets_might_conflict_p (set1, set2))
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer might break strict-aliasing rules");
+ }
+ }
+}
+
+
+/* Print a warning about if (); or if () .. else; constructs
+ via the special empty statement node that we create. INNER_THEN
+ and INNER_ELSE are the statement lists of the if and the else
+ block. */
+
+void
+empty_body_warning (tree inner_then, tree inner_else)
+{
+ if (extra_warnings)
+ {
+ if (TREE_CODE (inner_then) == STATEMENT_LIST
+ && STATEMENT_LIST_TAIL (inner_then))
+ inner_then = STATEMENT_LIST_TAIL (inner_then)->stmt;
+
+ if (inner_else && TREE_CODE (inner_else) == STATEMENT_LIST
+ && STATEMENT_LIST_TAIL (inner_else))
+ inner_else = STATEMENT_LIST_TAIL (inner_else)->stmt;
+
+ if (IS_EMPTY_STMT (inner_then) && !inner_else)
+ warning (OPT_Wextra, "%Hempty body in an if-statement",
+ EXPR_LOCUS (inner_then));
+
+ if (inner_else && IS_EMPTY_STMT (inner_else))
+ warning (OPT_Wextra, "%Hempty body in an else-statement",
+ EXPR_LOCUS (inner_else));
+ }
+}
+
+
/* Nonzero if constant C has a value that is permissible
for type TYPE (an INTEGER_TYPE). */
@@ -1288,7 +1064,9 @@ vector_types_convertible_p (tree t1, tree t2)
{
return targetm.vector_opaque_p (t1)
|| targetm.vector_opaque_p (t2)
- || (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+ || (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+ && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE ||
+ TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
&& INTEGRAL_TYPE_P (TREE_TYPE (t1))
== INTEGRAL_TYPE_P (TREE_TYPE (t2)));
}
@@ -1309,20 +1087,22 @@ convert_and_check (tree type, tree expr)
/* Do not diagnose overflow in a constant expression merely
because a conversion overflowed. */
- TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (expr);
+ TREE_CONSTANT_OVERFLOW (t) = CONSTANT_CLASS_P (expr)
+ && TREE_CONSTANT_OVERFLOW (expr);
/* No warning for converting 0x80000000 to int. */
- if (!(TREE_UNSIGNED (type) < TREE_UNSIGNED (TREE_TYPE (expr))
+ if (!(TYPE_UNSIGNED (type) < TYPE_UNSIGNED (TREE_TYPE (expr))
&& TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr))))
/* If EXPR fits in the unsigned version of TYPE,
don't warn unless pedantic. */
if ((pedantic
- || TREE_UNSIGNED (type)
- || ! constant_fits_type_p (expr,
- c_common_unsigned_type (type)))
- && skip_evaluation == 0)
- warning ("overflow in implicit constant conversion");
+ || TYPE_UNSIGNED (type)
+ || !constant_fits_type_p (expr,
+ c_common_unsigned_type (type)))
+ && skip_evaluation == 0)
+ warning (OPT_Woverflow,
+ "overflow in implicit constant conversion");
}
else
unsigned_conversion_warning (t, expr);
@@ -1368,14 +1148,13 @@ static int warning_candidate_p (tree);
static void warn_for_collisions (struct tlist *);
static void warn_for_collisions_1 (tree, tree, struct tlist *, int);
static struct tlist *new_tlist (struct tlist *, tree, tree);
-static void verify_sequence_points (tree);
/* Create a new struct tlist and fill in its fields. */
static struct tlist *
new_tlist (struct tlist *next, tree t, tree writer)
{
struct tlist *l;
- l = obstack_alloc (&tlist_obstack, sizeof *l);
+ l = XOBNEW (&tlist_obstack, struct tlist);
l->next = next;
l->expr = t;
l->writer = writer;
@@ -1391,9 +1170,9 @@ add_tlist (struct tlist **to, struct tlist *add, tree exclude_writer, int copy)
while (add)
{
struct tlist *next = add->next;
- if (! copy)
+ if (!copy)
add->next = *to;
- if (! exclude_writer || add->writer != exclude_writer)
+ if (!exclude_writer || add->writer != exclude_writer)
*to = copy ? new_tlist (*to, add->expr, add->writer) : add;
add = next;
}
@@ -1423,10 +1202,10 @@ merge_tlist (struct tlist **to, struct tlist *add, int copy)
if (tmp2->expr == add->expr)
{
found = 1;
- if (! tmp2->writer)
+ if (!tmp2->writer)
tmp2->writer = add->writer;
}
- if (! found)
+ if (!found)
{
*end = copy ? add : new_tlist (NULL, add->expr, add->writer);
end = &(*end)->next;
@@ -1455,11 +1234,11 @@ warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
{
if (list->expr == written
&& list->writer != writer
- && (! only_writes || list->writer))
+ && (!only_writes || list->writer)
+ && DECL_NAME (list->expr))
{
warned_ids = new_tlist (warned_ids, written, NULL_TREE);
- warning ("operation on `%s' may be undefined",
- IDENTIFIER_POINTER (DECL_NAME (list->expr)));
+ warning (0, "operation on %qE may be undefined", list->expr);
}
list = list->next;
}
@@ -1519,7 +1298,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
{
struct tlist *tmp_before, *tmp_nosp, *tmp_list2, *tmp_list3;
enum tree_code code;
- char class;
+ enum tree_code_class cl;
/* X may be NULL if it is the operand of an empty statement expression
({ }). */
@@ -1528,7 +1307,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
restart:
code = TREE_CODE (x);
- class = TREE_CODE_CLASS (code);
+ cl = TREE_CODE_CLASS (code);
if (warning_candidate_p (x))
{
@@ -1643,9 +1422,9 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
if (t->expr == x)
break;
- if (! t)
+ if (!t)
{
- t = obstack_alloc (&tlist_obstack, sizeof *t);
+ t = XOBNEW (&tlist_obstack, struct tlist_cache);
t->next = save_expr_cache;
t->expr = x;
save_expr_cache = t;
@@ -1668,47 +1447,37 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
add_tlist (pno_sp, t->cache_after_sp, NULL_TREE, 1);
return;
}
- default:
- break;
- }
- if (class == '1')
- {
- if (first_rtl_op (code) == 0)
- return;
- x = TREE_OPERAND (x, 0);
- writer = 0;
- goto restart;
- }
-
- switch (class)
- {
- case 'r':
- case '<':
- case '2':
- case 'b':
- case 'e':
- case 's':
- case 'x':
- {
- int lp;
- int max = first_rtl_op (TREE_CODE (x));
- for (lp = 0; lp < max; lp++)
- {
- tmp_before = tmp_nosp = 0;
- verify_tree (TREE_OPERAND (x, lp), &tmp_before, &tmp_nosp, NULL_TREE);
- merge_tlist (&tmp_nosp, tmp_before, 0);
- add_tlist (pno_sp, tmp_nosp, NULL_TREE, 0);
- }
- break;
- }
+ default:
+ /* For other expressions, simply recurse on their operands.
+ Manual tail recursion for unary expressions.
+ Other non-expressions need not be processed. */
+ if (cl == tcc_unary)
+ {
+ x = TREE_OPERAND (x, 0);
+ writer = 0;
+ goto restart;
+ }
+ else if (IS_EXPR_CODE_CLASS (cl))
+ {
+ int lp;
+ int max = TREE_CODE_LENGTH (TREE_CODE (x));
+ for (lp = 0; lp < max; lp++)
+ {
+ tmp_before = tmp_nosp = 0;
+ verify_tree (TREE_OPERAND (x, lp), &tmp_before, &tmp_nosp, 0);
+ merge_tlist (&tmp_nosp, tmp_before, 0);
+ add_tlist (pno_sp, tmp_nosp, NULL_TREE, 0);
+ }
+ }
+ return;
}
}
/* Try to warn for undefined behavior in EXPR due to missing sequence
points. */
-static void
+void
verify_sequence_points (tree expr)
{
struct tlist *before_sp = 0, *after_sp = 0;
@@ -1718,45 +1487,24 @@ verify_sequence_points (tree expr)
if (tlist_firstobj == 0)
{
gcc_obstack_init (&tlist_obstack);
- tlist_firstobj = obstack_alloc (&tlist_obstack, 0);
+ tlist_firstobj = (char *) obstack_alloc (&tlist_obstack, 0);
}
verify_tree (expr, &before_sp, &after_sp, 0);
warn_for_collisions (after_sp);
obstack_free (&tlist_obstack, tlist_firstobj);
}
-
-tree
-c_expand_expr_stmt (tree expr)
-{
- /* Do default conversion if safe and possibly important,
- in case within ({...}). */
- if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
- && (flag_isoc99 || lvalue_p (expr)))
- || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
- expr = default_conversion (expr);
-
- if (warn_sequence_point)
- verify_sequence_points (expr);
-
- if (TREE_TYPE (expr) != error_mark_node
- && !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr))
- && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
- error ("expression statement has incomplete type");
-
- last_expr_type = TREE_TYPE (expr);
- return add_stmt (build_stmt (EXPR_STMT, expr));
-}
/* Validate the expression after `case' and apply default promotions. */
-tree
+static tree
check_case_value (tree value)
{
if (value == NULL_TREE)
return value;
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
+ /* ??? Can we ever get nops here for a valid case value? We
+ shouldn't for C. */
STRIP_TYPE_NOPS (value);
/* In C++, the following is allowed:
@@ -1771,21 +1519,89 @@ check_case_value (tree value)
value = fold (value);
}
- if (TREE_CODE (value) != INTEGER_CST
- && value != error_mark_node)
+ if (TREE_CODE (value) == INTEGER_CST)
+ /* Promote char or short to int. */
+ value = perform_integral_promotions (value);
+ else if (value != error_mark_node)
{
error ("case label does not reduce to an integer constant");
value = error_mark_node;
}
- else
- /* Promote char or short to int. */
- value = default_conversion (value);
constant_expression_warning (value);
return value;
}
+/* See if the case values LOW and HIGH are in the range of the original
+ type (i.e. before the default conversion to int) of the switch testing
+ expression.
+ TYPE is the promoted type of the testing expression, and ORIG_TYPE is
+ the type before promoting it. CASE_LOW_P is a pointer to the lower
+ bound of the case label, and CASE_HIGH_P is the upper bound or NULL
+ if the case is not a case range.
+ The caller has to make sure that we are not called with NULL for
+ CASE_LOW_P (i.e. the default case).
+ Returns true if the case label is in range of ORIG_TYPE (saturated or
+ untouched) or false if the label is out of range. */
+
+static bool
+check_case_bounds (tree type, tree orig_type,
+ tree *case_low_p, tree *case_high_p)
+{
+ tree min_value, max_value;
+ tree case_low = *case_low_p;
+ tree case_high = case_high_p ? *case_high_p : case_low;
+
+ /* If there was a problem with the original type, do nothing. */
+ if (orig_type == error_mark_node)
+ return true;
+
+ min_value = TYPE_MIN_VALUE (orig_type);
+ max_value = TYPE_MAX_VALUE (orig_type);
+
+ /* Case label is less than minimum for type. */
+ if (tree_int_cst_compare (case_low, min_value) < 0
+ && tree_int_cst_compare (case_high, min_value) < 0)
+ {
+ warning (0, "case label value is less than minimum value for type");
+ return false;
+ }
+
+ /* Case value is greater than maximum for type. */
+ if (tree_int_cst_compare (case_low, max_value) > 0
+ && tree_int_cst_compare (case_high, max_value) > 0)
+ {
+ warning (0, "case label value exceeds maximum value for type");
+ return false;
+ }
+
+ /* Saturate lower case label value to minimum. */
+ if (tree_int_cst_compare (case_high, min_value) >= 0
+ && tree_int_cst_compare (case_low, min_value) < 0)
+ {
+ warning (0, "lower value in case label range"
+ " less than minimum value for type");
+ case_low = min_value;
+ }
+
+ /* Saturate upper case label value to maximum. */
+ if (tree_int_cst_compare (case_low, max_value) <= 0
+ && tree_int_cst_compare (case_high, max_value) > 0)
+ {
+ warning (0, "upper value in case label range"
+ " exceeds maximum value for type");
+ case_high = max_value;
+ }
+
+ if (*case_low_p != case_low)
+ *case_low_p = convert (type, case_low);
+ if (case_high_p && *case_high_p != case_high)
+ *case_high_p = convert (type, case_high);
+
+ return true;
+}
+
/* Return an integer type with BITS bits of precision,
that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
@@ -1857,7 +1673,7 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
if (mode == TYPE_MODE (widest_integer_literal_type_node))
return unsignedp ? widest_unsigned_literal_type_node
- : widest_integer_literal_type_node;
+ : widest_integer_literal_type_node;
if (mode == QImode)
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
@@ -1887,46 +1703,51 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
if (mode == TYPE_MODE (void_type_node))
return void_type_node;
-
+
if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
- return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
+ return (unsignedp
+ ? make_unsigned_type (GET_MODE_PRECISION (mode))
+ : make_signed_type (GET_MODE_PRECISION (mode)));
if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
- return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
-
- switch (mode)
- {
- case V16QImode:
- return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
- case V8HImode:
- return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
- case V4SImode:
- return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
- case V2DImode:
- return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
- case V2SImode:
- return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
- case V2HImode:
- return unsignedp ? unsigned_V2HI_type_node : V2HI_type_node;
- case V4HImode:
- return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
- case V8QImode:
- return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
- case V1DImode:
- return unsignedp ? unsigned_V1DI_type_node : V1DI_type_node;
- case V16SFmode:
- return V16SF_type_node;
- case V4SFmode:
- return V4SF_type_node;
- case V2SFmode:
- return V2SF_type_node;
- case V2DFmode:
- return V2DF_type_node;
- case V4DFmode:
- return V4DF_type_node;
- default:
- break;
+ return (unsignedp
+ ? make_unsigned_type (GET_MODE_PRECISION (mode))
+ : make_signed_type (GET_MODE_PRECISION (mode)));
+
+ if (COMPLEX_MODE_P (mode))
+ {
+ enum machine_mode inner_mode;
+ tree inner_type;
+
+ if (mode == TYPE_MODE (complex_float_type_node))
+ return complex_float_type_node;
+ if (mode == TYPE_MODE (complex_double_type_node))
+ return complex_double_type_node;
+ if (mode == TYPE_MODE (complex_long_double_type_node))
+ return complex_long_double_type_node;
+
+ if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
+ return complex_integer_type_node;
+
+ inner_mode = GET_MODE_INNER (mode);
+ inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+ if (inner_type != NULL_TREE)
+ return build_complex_type (inner_type);
}
+ else if (VECTOR_MODE_P (mode))
+ {
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ tree inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+ if (inner_type != NULL_TREE)
+ return build_vector_type_for_mode (inner_type, mode);
+ }
+
+ if (mode == TYPE_MODE (dfloat32_type_node))
+ return dfloat32_type_node;
+ if (mode == TYPE_MODE (dfloat64_type_node))
+ return dfloat64_type_node;
+ if (mode == TYPE_MODE (dfloat128_type_node))
+ return dfloat128_type_node;
for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
if (TYPE_MODE (TREE_VALUE (t)) == mode)
@@ -2008,44 +1829,80 @@ c_common_signed_type (tree type)
tree
c_common_signed_or_unsigned_type (int unsignedp, tree type)
{
- if (! INTEGRAL_TYPE_P (type)
- || TREE_UNSIGNED (type) == unsignedp)
+ if (!INTEGRAL_TYPE_P (type)
+ || TYPE_UNSIGNED (type) == unsignedp)
return type;
- /* Must check the mode of the types, not the precision. Enumeral types
- in C++ have precision set to match their range, but may use a wider
- mode to match an ABI. If we change modes, we may wind up with bad
- conversions. */
-
- if (TYPE_MODE (type) == TYPE_MODE (signed_char_type_node))
+ /* For ENUMERAL_TYPEs in C++, must check the mode of the types, not
+ the precision; they have precision set to match their range, but
+ may use a wider mode to match an ABI. If we change modes, we may
+ wind up with bad conversions. For INTEGER_TYPEs in C, must check
+ the precision as well, so as to yield correct results for
+ bit-field types. C++ does not have these separate bit-field
+ types, and producing a signed or unsigned variant of an
+ ENUMERAL_TYPE may cause other problems as well. */
+
+#define TYPE_OK(node) \
+ (TYPE_MODE (type) == TYPE_MODE (node) \
+ && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
+ if (TYPE_OK (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (integer_type_node))
+ if (TYPE_OK (integer_type_node))
return unsignedp ? unsigned_type_node : integer_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (short_integer_type_node))
+ if (TYPE_OK (short_integer_type_node))
return unsignedp ? short_unsigned_type_node : short_integer_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (long_integer_type_node))
+ if (TYPE_OK (long_integer_type_node))
return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (long_long_integer_type_node))
+ if (TYPE_OK (long_long_integer_type_node))
return (unsignedp ? long_long_unsigned_type_node
: long_long_integer_type_node);
- if (TYPE_MODE (type) == TYPE_MODE (widest_integer_literal_type_node))
+ if (TYPE_OK (widest_integer_literal_type_node))
return (unsignedp ? widest_unsigned_literal_type_node
: widest_integer_literal_type_node);
#if HOST_BITS_PER_WIDE_INT >= 64
- if (TYPE_MODE (type) == TYPE_MODE (intTI_type_node))
+ if (TYPE_OK (intTI_type_node))
return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
#endif
- if (TYPE_MODE (type) == TYPE_MODE (intDI_type_node))
+ if (TYPE_OK (intDI_type_node))
return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (intSI_type_node))
+ if (TYPE_OK (intSI_type_node))
return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (intHI_type_node))
+ if (TYPE_OK (intHI_type_node))
return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
- if (TYPE_MODE (type) == TYPE_MODE (intQI_type_node))
+ if (TYPE_OK (intQI_type_node))
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+#undef TYPE_OK
- return type;
+ if (c_dialect_cxx ())
+ return type;
+ else
+ return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
+}
+
+/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
+
+tree
+c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
+{
+ /* Extended integer types of the same width as a standard type have
+ lesser rank, so those of the same width as int promote to int or
+ unsigned int and are valid for printf formats expecting int or
+ unsigned int. To avoid such special cases, avoid creating
+ extended integer types for bit-fields if a standard integer type
+ is available. */
+ if (width == TYPE_PRECISION (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+ if (width == TYPE_PRECISION (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+ if (width == TYPE_PRECISION (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+ if (width == TYPE_PRECISION (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+ if (width == TYPE_PRECISION (long_long_integer_type_node))
+ return (unsignedp ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+ return build_nonstandard_integer_type (width, unsignedp);
}
/* The C version of the register_builtin_type langhook. */
@@ -2079,7 +1936,7 @@ min_precision (tree value, int unsignedp)
a bit-wise negation, so use that operation instead. */
if (tree_int_cst_sgn (value) < 0)
- value = fold (build1 (BIT_NOT_EXPR, TREE_TYPE (value), value));
+ value = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (value), value);
/* Return the number of bits needed, taking into account the fact
that we need one more bit for a signed than unsigned type. */
@@ -2089,12 +1946,11 @@ min_precision (tree value, int unsignedp)
else
log = tree_floor_log2 (value);
- return log + 1 + ! unsignedp;
+ return log + 1 + !unsignedp;
}
/* Print an error message for invalid operands to arith operation
- CODE. NOP_EXPR is used as a special case (see
- c_common_truthvalue_conversion). */
+ CODE. */
void
binary_op_error (enum tree_code code)
@@ -2103,10 +1959,6 @@ binary_op_error (enum tree_code code)
switch (code)
{
- case NOP_EXPR:
- error ("invalid truth-value expression");
- return;
-
case PLUS_EXPR:
opname = "+"; break;
case MINUS_EXPR:
@@ -2149,11 +2001,8 @@ binary_op_error (enum tree_code code)
opname = "||"; break;
case BIT_XOR_EXPR:
opname = "^"; break;
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- opname = "rotate"; break;
default:
- opname = "unknown"; break;
+ gcc_unreachable ();
}
error ("invalid operands to binary %s", opname);
}
@@ -2194,9 +2043,9 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
but it *requires* conversion to FINAL_TYPE. */
if (op0 == primop0 && TREE_TYPE (op0) != *restype_ptr)
- unsignedp0 = TREE_UNSIGNED (TREE_TYPE (op0));
+ unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (op0));
if (op1 == primop1 && TREE_TYPE (op1) != *restype_ptr)
- unsignedp1 = TREE_UNSIGNED (TREE_TYPE (op1));
+ unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (op1));
/* If one of the operands must be floated, we cannot optimize. */
real1 = TREE_CODE (TREE_TYPE (primop0)) == REAL_TYPE;
@@ -2207,7 +2056,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
the second arg is 0. */
if (TREE_CONSTANT (primop0)
- && ! integer_zerop (primop1) && ! real_zerop (primop1))
+ && !integer_zerop (primop1) && !real_zerop (primop1))
{
tree tem = primop0;
int temi = unsignedp0;
@@ -2268,20 +2117,12 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
int min_gt, max_gt, min_lt, max_lt;
tree maxval, minval;
/* 1 if comparison is nominally unsigned. */
- int unsignedp = TREE_UNSIGNED (*restype_ptr);
+ int unsignedp = TYPE_UNSIGNED (*restype_ptr);
tree val;
type = c_common_signed_or_unsigned_type (unsignedp0,
TREE_TYPE (primop0));
- /* In C, if TYPE is an enumeration, then we need to get its
- min/max values from it's underlying integral type, not the
- enumerated type itself. In C++, TYPE_MAX_VALUE and
- TYPE_MIN_VALUE have already been set correctly on the
- enumeration type. */
- if (!c_dialect_cxx() && TREE_CODE (type) == ENUMERAL_TYPE)
- type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0);
-
maxval = TYPE_MAX_VALUE (type);
minval = TYPE_MIN_VALUE (type);
@@ -2289,7 +2130,16 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
*restype_ptr = c_common_signed_type (*restype_ptr);
if (TREE_TYPE (primop1) != *restype_ptr)
- primop1 = convert (*restype_ptr, primop1);
+ {
+ /* Convert primop1 to target type, but do not introduce
+ additional overflow. We know primop1 is an int_cst. */
+ tree tmp = build_int_cst_wide (*restype_ptr,
+ TREE_INT_CST_LOW (primop1),
+ TREE_INT_CST_HIGH (primop1));
+
+ primop1 = force_fit_type (tmp, 0, TREE_OVERFLOW (primop1),
+ TREE_CONSTANT_OVERFLOW (primop1));
+ }
if (type != *restype_ptr)
{
minval = convert (*restype_ptr, minval);
@@ -2389,16 +2239,16 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
if (TREE_CODE (primop0) != INTEGER_CST)
{
if (val == truthvalue_false_node)
- warning ("comparison is always false due to limited range of data type");
+ warning (0, "comparison is always false due to limited range of data type");
if (val == truthvalue_true_node)
- warning ("comparison is always true due to limited range of data type");
+ warning (0, "comparison is always true due to limited range of data type");
}
if (val != 0)
{
/* Don't forget to evaluate PRIMOP0 if it has side effects. */
if (TREE_SIDE_EFFECTS (primop0))
- return build (COMPOUND_EXPR, TREE_TYPE (val), primop0, val);
+ return build2 (COMPOUND_EXPR, TREE_TYPE (val), primop0, val);
return val;
}
@@ -2406,6 +2256,14 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
in the type of the operand that is not constant.
TYPE is already properly set. */
}
+
+ /* If either arg is decimal float and the other is float, find the
+ proper common type to use for comparison. */
+ else if (real1 && real2
+ && (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0)))
+ || DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1)))))
+ type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
+
else if (real1 && real2
&& (TYPE_PRECISION (TREE_TYPE (primop0))
== TYPE_PRECISION (TREE_TYPE (primop1))))
@@ -2425,7 +2283,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
{
type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
type = c_common_signed_or_unsigned_type (unsignedp0
- || TREE_UNSIGNED (*restype_ptr),
+ || TYPE_UNSIGNED (*restype_ptr),
type);
/* Make sure shorter operand is extended the right way
to match the longer operand. */
@@ -2447,7 +2305,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
primop1 = op1;
if (!real1 && !real2 && integer_zerop (primop1)
- && TREE_UNSIGNED (*restype_ptr))
+ && TYPE_UNSIGNED (*restype_ptr))
{
tree value = 0;
switch (code)
@@ -2458,19 +2316,19 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
>= 0, the signedness of the comparison isn't an issue,
so suppress the warning. */
if (extra_warnings && !in_system_header
- && ! (TREE_CODE (primop0) == INTEGER_CST
- && ! TREE_OVERFLOW (convert (c_common_signed_type (type),
- primop0))))
- warning ("comparison of unsigned expression >= 0 is always true");
+ && !(TREE_CODE (primop0) == INTEGER_CST
+ && !TREE_OVERFLOW (convert (c_common_signed_type (type),
+ primop0))))
+ warning (0, "comparison of unsigned expression >= 0 is always true");
value = truthvalue_true_node;
break;
case LT_EXPR:
if (extra_warnings && !in_system_header
- && ! (TREE_CODE (primop0) == INTEGER_CST
- && ! TREE_OVERFLOW (convert (c_common_signed_type (type),
- primop0))))
- warning ("comparison of unsigned expression < 0 is always false");
+ && !(TREE_CODE (primop0) == INTEGER_CST
+ && !TREE_OVERFLOW (convert (c_common_signed_type (type),
+ primop0))))
+ warning (0, "comparison of unsigned expression < 0 is always false");
value = truthvalue_false_node;
break;
@@ -2482,8 +2340,8 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
{
/* Don't forget to evaluate PRIMOP0 if it has side effects. */
if (TREE_SIDE_EFFECTS (primop0))
- return build (COMPOUND_EXPR, TREE_TYPE (value),
- primop0, value);
+ return build2 (COMPOUND_EXPR, TREE_TYPE (value),
+ primop0, value);
return value;
}
}
@@ -2503,10 +2361,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
tree
pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
{
- tree size_exp;
-
- tree result;
- tree folded;
+ tree size_exp, ret;
/* The result is a pointer of the same type that is being added. */
@@ -2515,7 +2370,7 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
if (pedantic || warn_pointer_arith)
- pedwarn ("pointer of type `void *' used in arithmetic");
+ pedwarn ("pointer of type %<void *%> used in arithmetic");
size_exp = integer_one_node;
}
else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
@@ -2533,13 +2388,19 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
else
size_exp = size_in_bytes (TREE_TYPE (result_type));
+ /* We are manipulating pointer values, so we don't need to warn
+ about relying on undefined signed overflow. We disable the
+ warning here because we use integer types so fold won't know that
+ they are really pointers. */
+ fold_defer_overflow_warnings ();
+
/* If what we are about to multiply by the size of the elements
contains a constant term, apply distributive law
and multiply that constant term separately.
This helps produce common subexpressions. */
if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
- && ! TREE_CONSTANT (intop)
+ && !TREE_CONSTANT (intop)
&& TREE_CONSTANT (TREE_OPERAND (intop, 1))
&& TREE_CONSTANT (size_exp)
/* If the constant comes from pointer subtraction,
@@ -2548,7 +2409,7 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
/* If the constant is unsigned, and smaller than the pointer size,
then we must skip this optimization. This is because it could cause
an overflow error if the constant is negative but INTOP is not. */
- && (! TREE_UNSIGNED (TREE_TYPE (intop))
+ && (!TYPE_UNSIGNED (TREE_TYPE (intop))
|| (TYPE_PRECISION (TREE_TYPE (intop))
== TYPE_PRECISION (TREE_TYPE (ptrop)))))
{
@@ -2568,9 +2429,9 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
so the multiply won't overflow spuriously. */
if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
- || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
+ || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
- TREE_UNSIGNED (sizetype)), intop);
+ TYPE_UNSIGNED (sizetype)), intop);
/* Replace the integer argument with a suitable product by the object size.
Do this multiplication as signed, then convert to the appropriate
@@ -2581,17 +2442,17 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
+ ret = fold_build2 (resultcode, result_type, ptrop, intop);
- result = build (resultcode, result_type, ptrop, intop);
+ fold_undefer_and_ignore_overflow_warnings ();
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop);
- return folded;
+ return ret;
}
/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
- or validate its data type for an `if' or `while' statement or ?..: exp.
+ or for an `if' or `while' statement or ?..: exp. It should already
+ have been validated to be of suitable type; otherwise, a bad
+ diagnostic may result.
This preparation consists of taking the ordinary
representation of an expression expr and producing a valid tree
@@ -2604,77 +2465,77 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
tree
c_common_truthvalue_conversion (tree expr)
{
- if (TREE_CODE (expr) == ERROR_MARK)
- return expr;
-
- if (TREE_CODE (expr) == FUNCTION_DECL)
- expr = build_unary_op (ADDR_EXPR, expr, 0);
-
-#if 0 /* This appears to be wrong for C++. */
- /* These really should return error_mark_node after 2.4 is stable.
- But not all callers handle ERROR_MARK properly. */
- switch (TREE_CODE (TREE_TYPE (expr)))
- {
- case RECORD_TYPE:
- error ("struct type value used where scalar is required");
- return truthvalue_false_node;
-
- case UNION_TYPE:
- error ("union type value used where scalar is required");
- return truthvalue_false_node;
-
- case ARRAY_TYPE:
- error ("array type value used where scalar is required");
- return truthvalue_false_node;
-
- default:
- break;
- }
-#endif /* 0 */
-
switch (TREE_CODE (expr))
{
- case EQ_EXPR:
- case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
+ case EQ_EXPR: case NE_EXPR: case UNEQ_EXPR: case LTGT_EXPR:
+ case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
+ case UNLE_EXPR: case UNGE_EXPR: case UNLT_EXPR: case UNGT_EXPR:
+ case ORDERED_EXPR: case UNORDERED_EXPR:
+ if (TREE_TYPE (expr) == truthvalue_type_node)
+ return expr;
+ return build2 (TREE_CODE (expr), truthvalue_type_node,
+ TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
+
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
+ if (TREE_TYPE (expr) == truthvalue_type_node)
+ return expr;
+ return build2 (TREE_CODE (expr), truthvalue_type_node,
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)));
+
case TRUTH_NOT_EXPR:
- TREE_TYPE (expr) = truthvalue_type_node;
- return expr;
+ if (TREE_TYPE (expr) == truthvalue_type_node)
+ return expr;
+ return build1 (TREE_CODE (expr), truthvalue_type_node,
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
case ERROR_MARK:
return expr;
case INTEGER_CST:
- return integer_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
+ /* Avoid integer_zerop to ignore TREE_CONSTANT_OVERFLOW. */
+ return (TREE_INT_CST_LOW (expr) != 0 || TREE_INT_CST_HIGH (expr) != 0)
+ ? truthvalue_true_node
+ : truthvalue_false_node;
case REAL_CST:
- return real_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
+ return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0)
+ ? truthvalue_true_node
+ : truthvalue_false_node;
+
+ case FUNCTION_DECL:
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ /* Fall through. */
case ADDR_EXPR:
{
- if (TREE_CODE (TREE_OPERAND (expr, 0)) == FUNCTION_DECL
- && ! DECL_WEAK (TREE_OPERAND (expr, 0)))
+ tree inner = TREE_OPERAND (expr, 0);
+ if (DECL_P (inner)
+ && (TREE_CODE (inner) == PARM_DECL
+ || TREE_CODE (inner) == LABEL_DECL
+ || !DECL_WEAK (inner)))
{
- /* Common Ada/Pascal programmer's mistake. We always warn
+ /* Common Ada/Pascal programmer's mistake. We always warn
about this since it is so bad. */
- warning ("the address of `%D', will always evaluate as `true'",
- TREE_OPERAND (expr, 0));
+ warning (OPT_Waddress,
+ "the address of %qD will always evaluate as %<true%>",
+ inner);
return truthvalue_true_node;
}
/* If we are taking the address of an external decl, it might be
zero if it is weak, so we cannot optimize. */
- if (DECL_P (TREE_OPERAND (expr, 0))
- && DECL_EXTERNAL (TREE_OPERAND (expr, 0)))
+ if (DECL_P (inner)
+ && DECL_EXTERNAL (inner))
break;
- if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
- return build (COMPOUND_EXPR, truthvalue_type_node,
- TREE_OPERAND (expr, 0), truthvalue_true_node);
+ if (TREE_SIDE_EFFECTS (inner))
+ return build2 (COMPOUND_EXPR, truthvalue_type_node,
+ inner, truthvalue_true_node);
else
return truthvalue_true_node;
}
@@ -2697,65 +2558,36 @@ c_common_truthvalue_conversion (tree expr)
/* These don't change whether an object is zero or nonzero, but
we can't ignore them if their second arg has side-effects. */
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
- return build (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+ return build2 (COMPOUND_EXPR, truthvalue_type_node,
+ TREE_OPERAND (expr, 1),
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
else
return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
case COND_EXPR:
/* Distribute the conversion into the arms of a COND_EXPR. */
- return fold (build (COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0),
+ return fold_build3 (COND_EXPR, truthvalue_type_node,
+ TREE_OPERAND (expr, 0),
c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 2)));
case CONVERT_EXPR:
+ case NOP_EXPR:
/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
since that affects how `default_conversion' will behave. */
if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
break;
- /* Fall through.... */
- case NOP_EXPR:
/* If this is widening the argument, we can ignore it. */
if (TYPE_PRECISION (TREE_TYPE (expr))
>= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
break;
- case MINUS_EXPR:
- /* Perhaps reduce (x - y) != 0 to (x != y). The expressions
- aren't guaranteed to the be same for modes that can represent
- infinity, since if x and y are both +infinity, or both
- -infinity, then x - y is not a number.
-
- Note that this transformation is safe when x or y is NaN.
- (x - y) is then NaN, and both (x - y) != 0 and x != y will
- be false. */
- if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
- break;
- /* Fall through.... */
- case BIT_XOR_EXPR:
- /* This and MINUS_EXPR can be changed into a comparison of the
- two objects. */
- if (TREE_TYPE (TREE_OPERAND (expr, 0))
- == TREE_TYPE (TREE_OPERAND (expr, 1)))
- return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),
- TREE_OPERAND (expr, 1), 1);
- return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),
- fold (build1 (NOP_EXPR,
- TREE_TYPE (TREE_OPERAND (expr, 0)),
- TREE_OPERAND (expr, 1))), 1);
-
- case BIT_AND_EXPR:
- if (integer_onep (TREE_OPERAND (expr, 1))
- && TREE_TYPE (expr) != truthvalue_type_node)
- /* Using convert here would cause infinite recursion. */
- return build1 (NOP_EXPR, truthvalue_type_node, expr);
- break;
-
case MODIFY_EXPR:
- if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
- warning ("suggest parentheses around assignment used as truth value");
+ if (!TREE_NO_WARNING (expr))
+ warning (OPT_Wparentheses,
+ "suggest parentheses around assignment used as truth value");
break;
default:
@@ -2776,9 +2608,12 @@ c_common_truthvalue_conversion (tree expr)
return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
}
-static tree builtin_function_2 (const char *, const char *, tree, tree,
- int, enum built_in_class, int, int,
- tree);
+static void def_builtin_1 (enum built_in_function fncode,
+ const char *name,
+ enum built_in_class fnclass,
+ tree fntype, tree libtype,
+ bool both_p, bool fallback_p, bool nonansi_p,
+ tree fnattrs, bool implicit_p);
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
@@ -2788,11 +2623,30 @@ c_build_qualified_type (tree type, int type_quals)
{
if (type == error_mark_node)
return type;
-
+
if (TREE_CODE (type) == ARRAY_TYPE)
- return build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
+ {
+ tree t;
+ tree element_type = c_build_qualified_type (TREE_TYPE (type),
+ type_quals);
+
+ /* See if we already have an identically qualified type. */
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ {
+ if (TYPE_QUALS (strip_array_types (t)) == type_quals
+ && TYPE_NAME (t) == TYPE_NAME (type)
+ && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+ && attribute_list_equal (TYPE_ATTRIBUTES (t),
+ TYPE_ATTRIBUTES (type)))
+ break;
+ }
+ if (!t)
+ {
+ t = build_variant_type_copy (type);
+ TREE_TYPE (t) = element_type;
+ }
+ return t;
+ }
/* A restrict-qualified pointer type must be a pointer to object or
incomplete type. Note that the use of POINTER_TYPE_P also allows
@@ -2801,7 +2655,7 @@ c_build_qualified_type (tree type, int type_quals)
&& (!POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
{
- error ("invalid use of `restrict'");
+ error ("invalid use of %<restrict%>");
type_quals &= ~TYPE_QUAL_RESTRICT;
}
@@ -2814,7 +2668,7 @@ void
c_apply_type_quals_to_decl (int type_quals, tree decl)
{
tree type = TREE_TYPE (decl);
-
+
if (type == error_mark_node)
return;
@@ -2841,7 +2695,7 @@ c_apply_type_quals_to_decl (int type_quals, tree decl)
if (!type
|| !POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
- error ("invalid use of `restrict'");
+ error ("invalid use of %<restrict%>");
else if (flag_strict_aliasing && type == TREE_TYPE (decl))
/* Indicate we need to make a unique alias set for this pointer.
We can't do it here because it might be pointing to an
@@ -2850,6 +2704,51 @@ c_apply_type_quals_to_decl (int type_quals, tree decl)
}
}
+/* Hash function for the problem of multiple type definitions in
+ different files. This must hash all types that will compare
+ equal via comptypes to the same value. In practice it hashes
+ on some of the simple stuff and leaves the details to comptypes. */
+
+static hashval_t
+c_type_hash (const void *p)
+{
+ int i = 0;
+ int shift, size;
+ tree t = (tree) p;
+ tree t2;
+ switch (TREE_CODE (t))
+ {
+ /* For pointers, hash on pointee type plus some swizzling. */
+ case POINTER_TYPE:
+ return c_type_hash (TREE_TYPE (t)) ^ 0x3003003;
+ /* Hash on number of elements and total size. */
+ case ENUMERAL_TYPE:
+ shift = 3;
+ t2 = TYPE_VALUES (t);
+ break;
+ case RECORD_TYPE:
+ shift = 0;
+ t2 = TYPE_FIELDS (t);
+ break;
+ case QUAL_UNION_TYPE:
+ shift = 1;
+ t2 = TYPE_FIELDS (t);
+ break;
+ case UNION_TYPE:
+ shift = 2;
+ t2 = TYPE_FIELDS (t);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ for (; t2; t2 = TREE_CHAIN (t2))
+ i++;
+ size = TREE_INT_CST_LOW (TYPE_SIZE (t));
+ return ((size << 24) | (i << shift));
+}
+
+static GTY((param_is (union tree_node))) htab_t type_hash_table;
+
/* Return the typed-based alias set for T, which may be an expression
or a type. Return -1 if we don't do anything special. */
@@ -2857,6 +2756,7 @@ HOST_WIDE_INT
c_common_get_alias_set (tree t)
{
tree u;
+ PTR *slot;
/* Permit type-punning when accessing a union, provided the access
is directly through the union. For example, this code does not
@@ -2872,7 +2772,7 @@ c_common_get_alias_set (tree t)
return 0;
/* That's all the expressions we handle specially. */
- if (! TYPE_P (t))
+ if (!TYPE_P (t))
return -1;
/* The C standard guarantees that any object may be accessed via an
@@ -2889,7 +2789,7 @@ c_common_get_alias_set (tree t)
/* The C standard specifically allows aliasing between signed and
unsigned variants of the same type. We treat the signed
variant as canonical. */
- if (TREE_CODE (t) == INTEGER_TYPE && TREE_UNSIGNED (t))
+ if (TREE_CODE (t) == INTEGER_TYPE && TYPE_UNSIGNED (t))
{
tree t1 = c_common_signed_type (t);
@@ -2913,14 +2813,14 @@ c_common_get_alias_set (tree t)
technically, an `int **' and `const int **' cannot point at
the same thing.
- But, the standard is wrong. In particular, this code is
+ But, the standard is wrong. In particular, this code is
legal C++:
- int *ip;
- int **ipp = &ip;
- const int* const* cipp = &ipp;
+ int *ip;
+ int **ipp = &ip;
+ const int* const* cipp = ipp;
- And, it doesn't make sense for that to be legal unless you
+ And, it doesn't make sense for that to be legal unless you
can dereference IPP and CIPP. So, we ignore cv-qualifiers on
the pointed-to types. This issue has been reported to the
C++ committee. */
@@ -2929,6 +2829,66 @@ c_common_get_alias_set (tree t)
return get_alias_set (t1);
}
+ /* Handle the case of multiple type nodes referring to "the same" type,
+ which occurs with IMA. These share an alias set. FIXME: Currently only
+ C90 is handled. (In C99 type compatibility is not transitive, which
+ complicates things mightily. The alias set splay trees can theoretically
+ represent this, but insertion is tricky when you consider all the
+ different orders things might arrive in.) */
+
+ if (c_language != clk_c || flag_isoc99)
+ return -1;
+
+ /* Save time if there's only one input file. */
+ if (num_in_fnames == 1)
+ return -1;
+
+ /* Pointers need special handling if they point to any type that
+ needs special handling (below). */
+ if (TREE_CODE (t) == POINTER_TYPE)
+ {
+ tree t2;
+ /* Find bottom type under any nested POINTERs. */
+ for (t2 = TREE_TYPE (t);
+ TREE_CODE (t2) == POINTER_TYPE;
+ t2 = TREE_TYPE (t2))
+ ;
+ if (TREE_CODE (t2) != RECORD_TYPE
+ && TREE_CODE (t2) != ENUMERAL_TYPE
+ && TREE_CODE (t2) != QUAL_UNION_TYPE
+ && TREE_CODE (t2) != UNION_TYPE)
+ return -1;
+ if (TYPE_SIZE (t2) == 0)
+ return -1;
+ }
+ /* These are the only cases that need special handling. */
+ if (TREE_CODE (t) != RECORD_TYPE
+ && TREE_CODE (t) != ENUMERAL_TYPE
+ && TREE_CODE (t) != QUAL_UNION_TYPE
+ && TREE_CODE (t) != UNION_TYPE
+ && TREE_CODE (t) != POINTER_TYPE)
+ return -1;
+ /* Undefined? */
+ if (TYPE_SIZE (t) == 0)
+ return -1;
+
+ /* Look up t in hash table. Only one of the compatible types within each
+ alias set is recorded in the table. */
+ if (!type_hash_table)
+ type_hash_table = htab_create_ggc (1021, c_type_hash,
+ (htab_eq) lang_hooks.types_compatible_p,
+ NULL);
+ slot = htab_find_slot (type_hash_table, t, INSERT);
+ if (*slot != NULL)
+ {
+ TYPE_ALIAS_SET (t) = TYPE_ALIAS_SET ((tree)*slot);
+ return TYPE_ALIAS_SET ((tree)*slot);
+ }
+ else
+ /* Our caller will assign and record (in t) a new alias set; all we need
+ to do is remember t in the hash table. */
+ *slot = t;
+
return -1;
}
@@ -2936,22 +2896,22 @@ c_common_get_alias_set (tree t)
second parameter indicates which OPERATOR is being applied. The COMPLAIN
flag controls whether we should diagnose possibly ill-formed
constructs or not. */
+
tree
-c_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
+c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
{
const char *op_name;
tree value = NULL;
enum tree_code type_code = TREE_CODE (type);
- my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
- op_name = op == SIZEOF_EXPR ? "sizeof" : "__alignof__";
+ op_name = is_sizeof ? "sizeof" : "__alignof__";
if (type_code == FUNCTION_TYPE)
{
- if (op == SIZEOF_EXPR)
+ if (is_sizeof)
{
if (complain && (pedantic || warn_pointer_arith))
- pedwarn ("invalid application of `sizeof' to a function type");
+ pedwarn ("invalid application of %<sizeof%> to a function type");
value = size_one_node;
}
else
@@ -2961,33 +2921,33 @@ c_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
{
if (type_code == VOID_TYPE
&& complain && (pedantic || warn_pointer_arith))
- pedwarn ("invalid application of `%s' to a void type", op_name);
+ pedwarn ("invalid application of %qs to a void type", op_name);
value = size_one_node;
}
else if (!COMPLETE_TYPE_P (type))
{
if (complain)
- error ("invalid application of `%s' to incomplete type `%T' ",
+ error ("invalid application of %qs to incomplete type %qT ",
op_name, type);
value = size_zero_node;
}
else
{
- if (op == SIZEOF_EXPR)
+ if (is_sizeof)
/* Convert in case a char is more than one unit. */
value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
size_int (TYPE_PRECISION (char_type_node)
/ BITS_PER_UNIT));
else
- value = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
+ value = size_int (TYPE_ALIGN_UNIT (type));
}
/* VALUE will have an integer type with TYPE_IS_SIZETYPE set.
TYPE_IS_SIZETYPE means that certain things (like overflow) will
never happen. However, this node should really have type
`size_t', which is just a typedef for an ordinary integer type. */
- value = fold (build1 (NOP_EXPR, size_type_node, value));
- my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)), 20001021);
+ value = fold_convert (size_type_node, value);
+ gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
return value;
}
@@ -3003,17 +2963,17 @@ c_alignof_expr (tree expr)
tree t;
if (TREE_CODE (expr) == VAR_DECL)
- t = size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
+ t = size_int (DECL_ALIGN_UNIT (expr));
else if (TREE_CODE (expr) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
{
- error ("`__alignof' applied to a bit-field");
+ error ("%<__alignof%> applied to a bit-field");
t = size_one_node;
}
else if (TREE_CODE (expr) == COMPONENT_REF
&& TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
- t = size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT);
+ t = size_int (DECL_ALIGN_UNIT (TREE_OPERAND (expr, 1)));
else if (TREE_CODE (expr) == INDIRECT_REF)
{
@@ -3021,7 +2981,7 @@ c_alignof_expr (tree expr)
tree best = t;
int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
- while (TREE_CODE (t) == NOP_EXPR
+ while ((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR)
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
{
int thisalign;
@@ -3036,7 +2996,7 @@ c_alignof_expr (tree expr)
else
return c_alignof (TREE_TYPE (expr));
- return fold (build1 (NOP_EXPR, size_type_node, t));
+ return fold_convert (size_type_node, t);
}
/* Handle C and C++ default attributes. */
@@ -3059,24 +3019,24 @@ static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
static void c_init_attributes (void);
-/* Build tree nodes and builtin functions common to both C and C++ language
- frontends. */
-
-void
-c_common_nodes_and_builtins (void)
+enum c_builtin_type
{
- enum builtin_type
- {
#define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
#define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
+#define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \
+ NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
@@ -3085,17 +3045,71 @@ c_common_nodes_and_builtins (void)
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
#undef DEF_POINTER_TYPE
- BT_LAST
- };
+ BT_LAST
+};
+
+typedef enum c_builtin_type builtin_type;
+
+/* A temporary array for c_common_nodes_and_builtins. Used in
+ communication with def_fn_type. */
+static tree builtin_types[(int) BT_LAST + 1];
- typedef enum builtin_type builtin_type;
+/* A helper function for c_common_nodes_and_builtins. Build function type
+ for DEF with return type RET and N arguments. If VAR is true, then the
+ function should be variadic after those N arguments.
- tree builtin_types[(int) BT_LAST];
+ Takes special care not to ICE if any of the types involved are
+ error_mark_node, which indicates that said type is not in fact available
+ (see builtin_type_for_size). In which case the function type as a whole
+ should be error_mark_node. */
+
+static void
+def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
+{
+ tree args = NULL, t;
+ va_list list;
+ int i;
+
+ va_start (list, n);
+ for (i = 0; i < n; ++i)
+ {
+ builtin_type a = va_arg (list, builtin_type);
+ t = builtin_types[a];
+ if (t == error_mark_node)
+ goto egress;
+ args = tree_cons (NULL_TREE, t, args);
+ }
+ va_end (list);
+
+ args = nreverse (args);
+ if (!var)
+ args = chainon (args, void_list_node);
+
+ t = builtin_types[ret];
+ if (t == error_mark_node)
+ goto egress;
+ t = build_function_type (t, args);
+
+ egress:
+ builtin_types[def] = t;
+}
+
+/* Build tree nodes and builtin functions common to both C and C++ language
+ frontends. */
+
+void
+c_common_nodes_and_builtins (void)
+{
int wchar_type_size;
tree array_domain_type;
tree va_list_ref_type_node;
@@ -3136,43 +3150,45 @@ c_common_nodes_and_builtins (void)
/* These are types that c_common_type_for_size and
c_common_type_for_mode use. */
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- intQI_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- intHI_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- intSI_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- intDI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ intQI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ intHI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ intSI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ intDI_type_node));
#if HOST_BITS_PER_WIDE_INT >= 64
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("__int128_t"),
- intTI_type_node));
+ if (targetm.scalar_mode_supported_p (TImode))
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ get_identifier ("__int128_t"),
+ intTI_type_node));
#endif
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- unsigned_intQI_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- unsigned_intHI_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- unsigned_intSI_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- unsigned_intDI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ unsigned_intQI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ unsigned_intHI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ unsigned_intSI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ unsigned_intDI_type_node));
#if HOST_BITS_PER_WIDE_INT >= 64
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("__uint128_t"),
- unsigned_intTI_type_node));
+ if (targetm.scalar_mode_supported_p (TImode))
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ get_identifier ("__uint128_t"),
+ unsigned_intTI_type_node));
#endif
/* Create the widest literal types. */
widest_integer_literal_type_node
= make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- widest_integer_literal_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ widest_integer_literal_type_node));
widest_unsigned_literal_type_node
= make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
- widest_unsigned_literal_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ widest_unsigned_literal_type_node));
/* `unsigned long' is the standard type for sizeof.
Note that stddef.h uses `unsigned long',
@@ -3182,81 +3198,48 @@ c_common_nodes_and_builtins (void)
signed_size_type_node = c_common_signed_type (size_type_node);
set_sizetype (size_type_node);
+ pid_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (PID_TYPE)));
+
build_common_tree_nodes_2 (flag_short_double);
record_builtin_type (RID_FLOAT, NULL, float_type_node);
record_builtin_type (RID_DOUBLE, NULL, double_type_node);
record_builtin_type (RID_MAX, "long double", long_double_type_node);
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("complex int"),
- complex_integer_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("complex float"),
- complex_float_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("complex double"),
- complex_double_type_node));
- (*lang_hooks.decls.pushdecl)
+ /* Only supported decimal floating point extension if the target
+ actually supports underlying modes. */
+ if (targetm.scalar_mode_supported_p (SDmode)
+ && targetm.scalar_mode_supported_p (DDmode)
+ && targetm.scalar_mode_supported_p (TDmode))
+ {
+ record_builtin_type (RID_DFLOAT32, NULL, dfloat32_type_node);
+ record_builtin_type (RID_DFLOAT64, NULL, dfloat64_type_node);
+ record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node);
+ }
+
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ get_identifier ("complex int"),
+ complex_integer_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ get_identifier ("complex float"),
+ complex_float_type_node));
+ lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ get_identifier ("complex double"),
+ complex_double_type_node));
+ lang_hooks.decls.pushdecl
(build_decl (TYPE_DECL, get_identifier ("complex long double"),
complex_long_double_type_node));
- /* Types which are common to the fortran compiler and libf2c. When
- changing these, you also need to be concerned with f/com.h. */
-
- if (TYPE_PRECISION (float_type_node)
- == TYPE_PRECISION (long_integer_type_node))
- {
- g77_integer_type_node = long_integer_type_node;
- g77_uinteger_type_node = long_unsigned_type_node;
- }
- else if (TYPE_PRECISION (float_type_node)
- == TYPE_PRECISION (integer_type_node))
- {
- g77_integer_type_node = integer_type_node;
- g77_uinteger_type_node = unsigned_type_node;
- }
- else
- g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
-
- if (g77_integer_type_node != NULL_TREE)
- {
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("__g77_integer"),
- g77_integer_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("__g77_uinteger"),
- g77_uinteger_type_node));
- }
-
- if (TYPE_PRECISION (float_type_node) * 2
- == TYPE_PRECISION (long_integer_type_node))
- {
- g77_longint_type_node = long_integer_type_node;
- g77_ulongint_type_node = long_unsigned_type_node;
- }
- else if (TYPE_PRECISION (float_type_node) * 2
- == TYPE_PRECISION (long_long_integer_type_node))
- {
- g77_longint_type_node = long_long_integer_type_node;
- g77_ulongint_type_node = long_long_unsigned_type_node;
- }
- else
- g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
-
- if (g77_longint_type_node != NULL_TREE)
- {
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("__g77_longint"),
- g77_longint_type_node));
- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
- get_identifier ("__g77_ulongint"),
- g77_ulongint_type_node));
- }
+ if (c_dialect_cxx ())
+ /* For C++, make fileptr_type_node a distinct void * type until
+ FILE type is defined. */
+ fileptr_type_node = build_variant_type_copy (ptr_type_node);
record_builtin_type (RID_VOID, NULL, void_type_node);
- void_zero_node = build_int_2 (0, 0);
+ /* This node must not be shared. */
+ void_zero_node = make_node (INTEGER_CST);
TREE_TYPE (void_zero_node) = void_type_node;
void_list_node = build_void_list_node ();
@@ -3289,7 +3272,7 @@ c_common_nodes_and_builtins (void)
wchar_type_size = TYPE_PRECISION (wchar_type_node);
if (c_dialect_cxx ())
{
- if (TREE_UNSIGNED (wchar_type_node))
+ if (TYPE_UNSIGNED (wchar_type_node))
wchar_type_node = make_unsigned_type (wchar_type_size);
else
wchar_type_node = make_signed_type (wchar_type_size);
@@ -3318,18 +3301,10 @@ c_common_nodes_and_builtins (void)
= TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
- (*lang_hooks.decls.pushdecl)
+ lang_hooks.decls.pushdecl
(build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
va_list_type_node));
- (*lang_hooks.decls.pushdecl)
- (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"),
- ptrdiff_type_node));
-
- (*lang_hooks.decls.pushdecl)
- (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),
- sizetype));
-
if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
{
va_list_arg_type_node = va_list_ref_type_node =
@@ -3342,137 +3317,121 @@ c_common_nodes_and_builtins (void)
}
#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
- builtin_types[(int) ENUM] = VALUE;
-#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
- builtin_types[(int) ENUM] \
- = build_function_type (builtin_types[(int) RETURN], \
- void_list_node);
-#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
- builtin_types[(int) ENUM] \
- = build_function_type (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- void_list_node));
-#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- void_list_node)));
-#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG3], \
- void_list_node))));
-#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- tree_cons \
- (NULL_TREE, \
- builtin_types[(int) ARG3], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG4], \
- void_list_node)))));
-#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
- builtin_types[(int) ENUM] \
- = build_function_type (builtin_types[(int) RETURN], NULL_TREE);
-#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
- builtin_types[(int) ENUM] \
- = build_function_type (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- NULL_TREE));
-
-#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- NULL_TREE)));
-
-#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
- builtin_types[(int) ENUM] \
- = build_function_type \
- (builtin_types[(int) RETURN], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG1], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG2], \
- tree_cons (NULL_TREE, \
- builtin_types[(int) ARG3], \
- NULL_TREE))));
-
-#define DEF_POINTER_TYPE(ENUM, TYPE) \
- builtin_types[(int) ENUM] \
- = build_pointer_type (builtin_types[(int) TYPE]);
+ builtin_types[ENUM] = VALUE;
+#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
+ def_fn_type (ENUM, RETURN, 0, 0);
+#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
+ def_fn_type (ENUM, RETURN, 0, 1, ARG1);
+#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
+ def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
+#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
+#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+ def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
+#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
+#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) \
+ def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) \
+ def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
+#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
+ def_fn_type (ENUM, RETURN, 1, 0);
+#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
+ def_fn_type (ENUM, RETURN, 1, 1, ARG1);
+#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
+ def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
+#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+ def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
+#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
+#define DEF_POINTER_TYPE(ENUM, TYPE) \
+ builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
+
#include "builtin-types.def"
+
#undef DEF_PRIMITIVE_TYPE
#undef DEF_FUNCTION_TYPE_1
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
#undef DEF_POINTER_TYPE
+ builtin_types[(int) BT_LAST] = NULL_TREE;
c_init_attributes ();
-#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \
- BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT) \
- if (NAME) \
- { \
- tree decl; \
- \
- if (strncmp (NAME, "__builtin_", strlen ("__builtin_")) != 0) \
- abort (); \
- \
- if (!BOTH_P) \
- decl = builtin_function (NAME, builtin_types[TYPE], ENUM, \
- CLASS, \
- (FALLBACK_P \
- ? (NAME + strlen ("__builtin_")) \
- : NULL), \
- built_in_attributes[(int) ATTRS]); \
- else \
- decl = builtin_function_2 (NAME, \
- NAME + strlen ("__builtin_"), \
- builtin_types[TYPE], \
- builtin_types[LIBTYPE], \
- ENUM, \
- CLASS, \
- FALLBACK_P, \
- NONANSI_P, \
- built_in_attributes[(int) ATTRS]); \
- \
- built_in_decls[(int) ENUM] = decl; \
- if (IMPLICIT) \
- implicit_built_in_decls[(int) ENUM] = decl; \
- }
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
+ NONANSI_P, ATTRS, IMPLICIT, COND) \
+ if (NAME && COND) \
+ def_builtin_1 (ENUM, NAME, CLASS, \
+ builtin_types[(int) TYPE], \
+ builtin_types[(int) LIBTYPE], \
+ BOTH_P, FALLBACK_P, NONANSI_P, \
+ built_in_attributes[(int) ATTRS], IMPLICIT);
#include "builtins.def"
#undef DEF_BUILTIN
- (*targetm.init_builtins) ();
+ build_common_builtin_nodes ();
+
+ targetm.init_builtins ();
+ if (flag_mudflap)
+ mudflap_init ();
main_identifier_node = get_identifier ("main");
+
+ /* Create the built-in __null node. It is important that this is
+ not shared. */
+ null_node = make_node (INTEGER_CST);
+ TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
+
+ /* Since builtin_types isn't gc'ed, don't export these nodes. */
+ memset (builtin_types, 0, sizeof (builtin_types));
+}
+
+/* Look up the function in built_in_decls that corresponds to DECL
+ and set ASMSPEC as its user assembler name. DECL must be a
+ function decl that declares a builtin. */
+
+void
+set_builtin_user_assembler_name (tree decl, const char *asmspec)
+{
+ tree builtin;
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+ && asmspec != 0);
+
+ builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
+ set_user_assembler_name (builtin, asmspec);
+ if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
+ init_block_move_fn (asmspec);
+ else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
+ init_block_clear_fn (asmspec);
+}
+
+/* The number of named compound-literals generated thus far. */
+static GTY(()) int compound_literal_number;
+
+/* Set DECL_NAME for DECL, a VAR_DECL for a compound-literal. */
+
+void
+set_compound_literal_name (tree decl)
+{
+ char *name;
+ ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+ compound_literal_number);
+ compound_literal_number++;
+ DECL_NAME (decl) = get_identifier (name);
}
tree
@@ -3500,13 +3459,13 @@ void
disable_builtin_function (const char *name)
{
if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
- error ("cannot disable built-in function `%s'", name);
+ error ("cannot disable built-in function %qs", name);
else
{
- disabled_builtin *new = xmalloc (sizeof (disabled_builtin));
- new->name = name;
- new->next = disabled_builtins;
- disabled_builtins = new;
+ disabled_builtin *new_disabled_builtin = XNEW (disabled_builtin);
+ new_disabled_builtin->name = name;
+ new_disabled_builtin->next = disabled_builtins;
+ disabled_builtins = new_disabled_builtin;
}
}
@@ -3527,39 +3486,42 @@ builtin_function_disabled_p (const char *name)
}
-/* Possibly define a builtin function with one or two names. BUILTIN_NAME
- is an __builtin_-prefixed name; NAME is the ordinary name; one or both
- of these may be NULL (though both being NULL is useless).
- BUILTIN_TYPE is the type of the __builtin_-prefixed function;
- TYPE is the type of the function with the ordinary name. These
- may differ if the ordinary name is declared with a looser type to avoid
- conflicts with headers. FUNCTION_CODE and CLASS are as for
- builtin_function. If LIBRARY_NAME_P is nonzero, NAME is passed as
- the LIBRARY_NAME parameter to builtin_function when declaring BUILTIN_NAME.
- If NONANSI_P is nonzero, the name NAME is treated as a non-ANSI name;
- ATTRS is the tree list representing the builtin's function attributes.
- Returns the declaration of BUILTIN_NAME, if any, otherwise
- the declaration of NAME. Does not declare NAME if flag_no_builtin,
- or if NONANSI_P and flag_no_nonansi_builtin. */
+/* Worker for DEF_BUILTIN.
+ Possibly define a builtin function with one or two names.
+ Does not declare a non-__builtin_ function if flag_no_builtin, or if
+ nonansi_p and flag_no_nonansi_builtin. */
-static tree
-builtin_function_2 (const char *builtin_name, const char *name,
- tree builtin_type, tree type, int function_code,
- enum built_in_class class, int library_name_p,
- int nonansi_p, tree attrs)
+static void
+def_builtin_1 (enum built_in_function fncode,
+ const char *name,
+ enum built_in_class fnclass,
+ tree fntype, tree libtype,
+ bool both_p, bool fallback_p, bool nonansi_p,
+ tree fnattrs, bool implicit_p)
{
- tree bdecl = NULL_TREE;
- tree decl = NULL_TREE;
+ tree decl;
+ const char *libname;
+
+ if (fntype == error_mark_node)
+ return;
- if (builtin_name != 0)
- bdecl = builtin_function (builtin_name, builtin_type, function_code,
- class, library_name_p ? name : NULL, attrs);
+ gcc_assert ((!both_p && !fallback_p)
+ || !strncmp (name, "__builtin_",
+ strlen ("__builtin_")));
- if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
+ libname = name + strlen ("__builtin_");
+ decl = lang_hooks.builtin_function (name, fntype, fncode, fnclass,
+ (fallback_p ? libname : NULL),
+ fnattrs);
+ if (both_p
+ && !flag_no_builtin && !builtin_function_disabled_p (libname)
&& !(nonansi_p && flag_no_nonansi_builtin))
- decl = builtin_function (name, type, function_code, class, NULL, attrs);
+ lang_hooks.builtin_function (libname, libtype, fncode, fnclass,
+ NULL, fnattrs);
- return (bdecl != 0 ? bdecl : decl);
+ built_in_decls[(int) fncode] = decl;
+ if (implicit_p)
+ implicit_built_in_decls[(int) fncode] = decl;
}
/* Nonzero if the type T promotes to int. This is (nearly) the
@@ -3603,6 +3565,9 @@ self_promoting_args_p (tree parms)
{
tree type = TREE_VALUE (t);
+ if (type == error_mark_node)
+ continue;
+
if (TREE_CHAIN (t) == 0 && type != void_type_node)
return 0;
@@ -3639,225 +3604,6 @@ strip_pointer_operator (tree t)
return t;
}
-static tree expand_unordered_cmp (tree, tree, enum tree_code, enum tree_code);
-
-/* Expand a call to an unordered comparison function such as
- __builtin_isgreater(). FUNCTION is the function's declaration and
- PARAMS a list of the values passed. For __builtin_isunordered(),
- UNORDERED_CODE is UNORDERED_EXPR and ORDERED_CODE is NOP_EXPR. In
- other cases, UNORDERED_CODE and ORDERED_CODE are comparison codes
- that give the opposite of the desired result. UNORDERED_CODE is
- used for modes that can hold NaNs and ORDERED_CODE is used for the
- rest. */
-
-static tree
-expand_unordered_cmp (tree function, tree params,
- enum tree_code unordered_code,
- enum tree_code ordered_code)
-{
- tree arg0, arg1, type;
- enum tree_code code0, code1;
-
- /* Check that we have exactly two arguments. */
- if (params == 0 || TREE_CHAIN (params) == 0)
- {
- error ("too few arguments to function `%s'",
- IDENTIFIER_POINTER (DECL_NAME (function)));
- return error_mark_node;
- }
- else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
- {
- error ("too many arguments to function `%s'",
- IDENTIFIER_POINTER (DECL_NAME (function)));
- return error_mark_node;
- }
-
- arg0 = TREE_VALUE (params);
- arg1 = TREE_VALUE (TREE_CHAIN (params));
-
- code0 = TREE_CODE (TREE_TYPE (arg0));
- code1 = TREE_CODE (TREE_TYPE (arg1));
-
- /* Make sure that the arguments have a common type of REAL. */
- type = 0;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
- type = common_type (TREE_TYPE (arg0), TREE_TYPE (arg1));
-
- if (type == 0 || TREE_CODE (type) != REAL_TYPE)
- {
- error ("non-floating-point argument to function `%s'",
- IDENTIFIER_POINTER (DECL_NAME (function)));
- return error_mark_node;
- }
-
- if (unordered_code == UNORDERED_EXPR)
- {
- if (MODE_HAS_NANS (TYPE_MODE (type)))
- return build_binary_op (unordered_code,
- convert (type, arg0),
- convert (type, arg1),
- 0);
- else
- return integer_zero_node;
- }
-
- return build_unary_op (TRUTH_NOT_EXPR,
- build_binary_op (MODE_HAS_NANS (TYPE_MODE (type))
- ? unordered_code
- : ordered_code,
- convert (type, arg0),
- convert (type, arg1),
- 0),
- 0);
-}
-
-
-/* Recognize certain built-in functions so we can make tree-codes
- other than CALL_EXPR. We do this when it enables fold-const.c
- to do something useful. */
-/* ??? By rights this should go in builtins.c, but only C and C++
- implement build_{binary,unary}_op. Not exactly sure what bits
- of functionality are actually needed from those functions, or
- where the similar functionality exists in the other front ends. */
-
-tree
-expand_tree_builtin (tree function, tree params, tree coerced_params)
-{
- if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL)
- return NULL_TREE;
-
- switch (DECL_FUNCTION_CODE (function))
- {
- case BUILT_IN_ABS:
- case BUILT_IN_LABS:
- case BUILT_IN_LLABS:
- case BUILT_IN_IMAXABS:
- case BUILT_IN_FABS:
- case BUILT_IN_FABSL:
- case BUILT_IN_FABSF:
- if (coerced_params == 0)
- return integer_zero_node;
- return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
-
- case BUILT_IN_CONJ:
- case BUILT_IN_CONJF:
- case BUILT_IN_CONJL:
- if (coerced_params == 0)
- return integer_zero_node;
- return build_unary_op (CONJ_EXPR, TREE_VALUE (coerced_params), 0);
-
- case BUILT_IN_CREAL:
- case BUILT_IN_CREALF:
- case BUILT_IN_CREALL:
- if (coerced_params == 0)
- return integer_zero_node;
- return non_lvalue (build_unary_op (REALPART_EXPR,
- TREE_VALUE (coerced_params), 0));
-
- case BUILT_IN_CIMAG:
- case BUILT_IN_CIMAGF:
- case BUILT_IN_CIMAGL:
- if (coerced_params == 0)
- return integer_zero_node;
- return non_lvalue (build_unary_op (IMAGPART_EXPR,
- TREE_VALUE (coerced_params), 0));
-
- case BUILT_IN_ISGREATER:
- return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR);
-
- case BUILT_IN_ISGREATEREQUAL:
- return expand_unordered_cmp (function, params, UNLT_EXPR, LT_EXPR);
-
- case BUILT_IN_ISLESS:
- return expand_unordered_cmp (function, params, UNGE_EXPR, GE_EXPR);
-
- case BUILT_IN_ISLESSEQUAL:
- return expand_unordered_cmp (function, params, UNGT_EXPR, GT_EXPR);
-
- case BUILT_IN_ISLESSGREATER:
- return expand_unordered_cmp (function, params, UNEQ_EXPR, EQ_EXPR);
-
- case BUILT_IN_ISUNORDERED:
- return expand_unordered_cmp (function, params, UNORDERED_EXPR, NOP_EXPR);
-
- default:
- break;
- }
-
- return NULL_TREE;
-}
-
-/* Walk the statement tree, rooted at *tp. Apply FUNC to all the
- sub-trees of *TP in a pre-order traversal. FUNC is called with the
- DATA and the address of each sub-tree. If FUNC returns a non-NULL
- value, the traversal is aborted, and the value returned by FUNC is
- returned. If FUNC sets WALK_SUBTREES to zero, then the subtrees of
- the node being visited are not walked.
-
- We don't need a without_duplicates variant of this one because the
- statement tree is a tree, not a graph. */
-
-tree
-walk_stmt_tree (tree *tp, walk_tree_fn func, void *data)
-{
- enum tree_code code;
- int walk_subtrees;
- tree result;
- int i, len;
-
-#define WALK_SUBTREE(NODE) \
- do \
- { \
- result = walk_stmt_tree (&(NODE), func, data); \
- if (result) \
- return result; \
- } \
- while (0)
-
- /* Skip empty subtrees. */
- if (!*tp)
- return NULL_TREE;
-
- /* Skip subtrees below non-statement nodes. */
- if (!STATEMENT_CODE_P (TREE_CODE (*tp)))
- return NULL_TREE;
-
- /* Call the function. */
- walk_subtrees = 1;
- result = (*func) (tp, &walk_subtrees, data);
-
- /* If we found something, return it. */
- if (result)
- return result;
-
- /* FUNC may have modified the tree, recheck that we're looking at a
- statement node. */
- code = TREE_CODE (*tp);
- if (!STATEMENT_CODE_P (code))
- return NULL_TREE;
-
- /* Visit the subtrees unless FUNC decided that there was nothing
- interesting below this point in the tree. */
- if (walk_subtrees)
- {
- /* Walk over all the sub-trees of this operand. Statement nodes
- never contain RTL, and we needn't worry about TARGET_EXPRs. */
- len = TREE_CODE_LENGTH (code);
-
- /* Go through the subtrees. We need to do this in forward order so
- that the scope of a FOR_EXPR is handled properly. */
- for (i = 0; i < len; ++i)
- WALK_SUBTREE (TREE_OPERAND (*tp, i));
- }
-
- /* Finally visit the chain. This can be tail-recursion optimized if
- we write it this way. */
- return walk_stmt_tree (&TREE_CHAIN (*tp), func, data);
-
-#undef WALK_SUBTREE
-}
-
/* Used to compare case labels. K1 and K2 are actually tree nodes
representing case labels, or NULL_TREE for a `default' label.
Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after
@@ -3882,12 +3628,12 @@ case_compare (splay_tree_key k1, splay_tree_key k2)
case label was declared using the usual C/C++ syntax, rather than
the GNU case range extension. CASES is a tree containing all the
case ranges processed so far; COND is the condition for the
- switch-statement itself. Returns the CASE_LABEL created, or
- ERROR_MARK_NODE if no CASE_LABEL is created. */
+ switch-statement itself. Returns the CASE_LABEL_EXPR created, or
+ ERROR_MARK_NODE if no CASE_LABEL_EXPR is created. */
tree
-c_add_case_label (splay_tree cases, tree cond, tree low_value,
- tree high_value)
+c_add_case_label (splay_tree cases, tree cond, tree orig_type,
+ tree low_value, tree high_value)
{
tree type;
tree label;
@@ -3895,25 +3641,21 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
splay_tree_node node;
/* Create the LABEL_DECL itself. */
- label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- DECL_CONTEXT (label) = current_function_decl;
+ label = create_artificial_label ();
/* If there was an error processing the switch condition, bail now
before we get more confused. */
if (!cond || cond == error_mark_node)
- {
- /* Add a label anyhow so that the back-end doesn't think that
- the beginning of the switch is unreachable. */
- if (!cases->root)
- add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
- return error_mark_node;
- }
+ goto error_out;
if ((low_value && TREE_TYPE (low_value)
&& POINTER_TYPE_P (TREE_TYPE (low_value)))
|| (high_value && TREE_TYPE (high_value)
&& POINTER_TYPE_P (TREE_TYPE (high_value))))
- error ("pointers are not permitted as case values");
+ {
+ error ("pointers are not permitted as case values");
+ goto error_out;
+ }
/* Case ranges are a GNU extension. */
if (high_value && pedantic)
@@ -3924,29 +3666,35 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
{
low_value = check_case_value (low_value);
low_value = convert_and_check (type, low_value);
+ if (low_value == error_mark_node)
+ goto error_out;
}
if (high_value)
{
high_value = check_case_value (high_value);
high_value = convert_and_check (type, high_value);
+ if (high_value == error_mark_node)
+ goto error_out;
}
- /* If an error has occurred, bail out now. */
- if (low_value == error_mark_node || high_value == error_mark_node)
+ if (low_value && high_value)
{
- if (!cases->root)
- add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
- return error_mark_node;
+ /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
+ really a case range, even though it was written that way.
+ Remove the HIGH_VALUE to simplify later processing. */
+ if (tree_int_cst_equal (low_value, high_value))
+ high_value = NULL_TREE;
+ else if (!tree_int_cst_lt (low_value, high_value))
+ warning (0, "empty range specified");
}
- /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
- really a case range, even though it was written that way. Remove
- the HIGH_VALUE to simplify later processing. */
- if (tree_int_cst_equal (low_value, high_value))
- high_value = NULL_TREE;
- if (low_value && high_value
- && !tree_int_cst_lt (low_value, high_value))
- warning ("empty range specified");
+ /* See if the case is in range of the type of the original testing
+ expression. If both low_value and high_value are out of range,
+ don't insert the case label and return NULL_TREE. */
+ if (low_value
+ && !check_case_bounds (type, orig_type,
+ &low_value, high_value ? &high_value : NULL))
+ return NULL_TREE;
/* Look up the LOW_VALUE in the table of case labels we already
have. */
@@ -3993,7 +3741,7 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
/* If there was an overlap, issue an error. */
if (node)
{
- tree duplicate = CASE_LABEL_DECL ((tree) node->value);
+ tree duplicate = CASE_LABEL ((tree) node->value);
if (high_value)
{
@@ -4010,8 +3758,7 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
error ("multiple default labels in one switch");
error ("%Jthis is the first default label", duplicate);
}
- if (!cases->root)
- add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
+ goto error_out;
}
/* Add a CASE_LABEL to the statement-tree. */
@@ -4022,6 +3769,179 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
(splay_tree_value) case_label);
return case_label;
+
+ error_out:
+ /* Add a label so that the back-end doesn't think that the beginning of
+ the switch is unreachable. Note that we do not add a case label, as
+ that just leads to duplicates and thence to failure later on. */
+ if (!cases->root)
+ {
+ tree t = create_artificial_label ();
+ add_stmt (build_stmt (LABEL_EXPR, t));
+ }
+ return error_mark_node;
+}
+
+/* Subroutines of c_do_switch_warnings, called via splay_tree_foreach.
+ Used to verify that case values match up with enumerator values. */
+
+static void
+match_case_to_enum_1 (tree key, tree type, tree label)
+{
+ char buf[2 + 2*HOST_BITS_PER_WIDE_INT/4 + 1];
+
+ /* ??? Not working too hard to print the double-word value.
+ Should perhaps be done with %lwd in the diagnostic routines? */
+ if (TREE_INT_CST_HIGH (key) == 0)
+ snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED,
+ TREE_INT_CST_LOW (key));
+ else if (!TYPE_UNSIGNED (type)
+ && TREE_INT_CST_HIGH (key) == -1
+ && TREE_INT_CST_LOW (key) != 0)
+ snprintf (buf, sizeof (buf), "-" HOST_WIDE_INT_PRINT_UNSIGNED,
+ -TREE_INT_CST_LOW (key));
+ else
+ snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ TREE_INT_CST_HIGH (key), TREE_INT_CST_LOW (key));
+
+ if (TYPE_NAME (type) == 0)
+ warning (0, "%Jcase value %qs not in enumerated type",
+ CASE_LABEL (label), buf);
+ else
+ warning (0, "%Jcase value %qs not in enumerated type %qT",
+ CASE_LABEL (label), buf, type);
+}
+
+/* Subroutine of c_do_switch_warnings, called via splay_tree_foreach.
+ Used to verify that case values match up with enumerator values. */
+
+static int
+match_case_to_enum (splay_tree_node node, void *data)
+{
+ tree label = (tree) node->value;
+ tree type = (tree) data;
+
+ /* Skip default case. */
+ if (!CASE_LOW (label))
+ return 0;
+
+ /* If CASE_LOW_SEEN is not set, that means CASE_LOW did not appear
+ when we did our enum->case scan. Reset our scratch bit after. */
+ if (!CASE_LOW_SEEN (label))
+ match_case_to_enum_1 (CASE_LOW (label), type, label);
+ else
+ CASE_LOW_SEEN (label) = 0;
+
+ /* If CASE_HIGH is non-null, we have a range. If CASE_HIGH_SEEN is
+ not set, that means that CASE_HIGH did not appear when we did our
+ enum->case scan. Reset our scratch bit after. */
+ if (CASE_HIGH (label))
+ {
+ if (!CASE_HIGH_SEEN (label))
+ match_case_to_enum_1 (CASE_HIGH (label), type, label);
+ else
+ CASE_HIGH_SEEN (label) = 0;
+ }
+
+ return 0;
+}
+
+/* Handle -Wswitch*. Called from the front end after parsing the
+ switch construct. */
+/* ??? Should probably be somewhere generic, since other languages
+ besides C and C++ would want this. At the moment, however, C/C++
+ are the only tree-ssa languages that support enumerations at all,
+ so the point is moot. */
+
+void
+c_do_switch_warnings (splay_tree cases, location_t switch_location,
+ tree type, tree cond)
+{
+ splay_tree_node default_node;
+ splay_tree_node node;
+ tree chain;
+
+ if (!warn_switch && !warn_switch_enum && !warn_switch_default)
+ return;
+
+ default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
+ if (!default_node)
+ warning (OPT_Wswitch_default, "%Hswitch missing default case",
+ &switch_location);
+
+ /* From here on, we only care about about enumerated types. */
+ if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
+ return;
+
+ /* If the switch expression was an enumerated type, check that
+ exactly all enumeration literals are covered by the cases.
+ The check is made when -Wswitch was specified and there is no
+ default case, or when -Wswitch-enum was specified. */
+
+ if (!warn_switch_enum
+ && !(warn_switch && !default_node))
+ return;
+
+ /* Clearing COND if it is not an integer constant simplifies
+ the tests inside the loop below. */
+ if (TREE_CODE (cond) != INTEGER_CST)
+ cond = NULL_TREE;
+
+ /* The time complexity here is O(N*lg(N)) worst case, but for the
+ common case of monotonically increasing enumerators, it is
+ O(N), since the nature of the splay tree will keep the next
+ element adjacent to the root at all times. */
+
+ for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
+ {
+ tree value = TREE_VALUE (chain);
+ node = splay_tree_lookup (cases, (splay_tree_key) value);
+ if (node)
+ {
+ /* Mark the CASE_LOW part of the case entry as seen. */
+ tree label = (tree) node->value;
+ CASE_LOW_SEEN (label) = 1;
+ continue;
+ }
+
+ /* Even though there wasn't an exact match, there might be a
+ case range which includes the enumator's value. */
+ node = splay_tree_predecessor (cases, (splay_tree_key) value);
+ if (node && CASE_HIGH ((tree) node->value))
+ {
+ tree label = (tree) node->value;
+ int cmp = tree_int_cst_compare (CASE_HIGH (label), value);
+ if (cmp >= 0)
+ {
+ /* If we match the upper bound exactly, mark the CASE_HIGH
+ part of the case entry as seen. */
+ if (cmp == 0)
+ CASE_HIGH_SEEN (label) = 1;
+ continue;
+ }
+ }
+
+ /* We've now determined that this enumerated literal isn't
+ handled by the case labels of the switch statement. */
+
+ /* If the switch expression is a constant, we only really care
+ about whether that constant is handled by the switch. */
+ if (cond && tree_int_cst_compare (cond, value))
+ continue;
+
+ warning (0, "%Henumeration value %qE not handled in switch",
+ &switch_location, TREE_PURPOSE (chain));
+ }
+
+ /* Warn if there are case expressions that don't correspond to
+ enumerators. This can occur since C and C++ don't enforce
+ type-checking of assignments to enumeration variables.
+
+ The time complexity here is now always O(N) worst case, since
+ we should have marked both the lower bound and upper bound of
+ every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN
+ above. This scan also resets those fields. */
+ splay_tree_foreach (cases, match_case_to_enum, type);
}
/* Finish an expression taking the address of LABEL (an
@@ -4045,7 +3965,6 @@ finish_label_address_expr (tree label)
{
TREE_USED (label) = 1;
result = build1 (ADDR_EXPR, ptr_type_node, label);
- TREE_CONSTANT (result) = 1;
/* The current function in not necessarily uninlinable.
Computed gotos are incompatible with inlining, but the value
here could be used only in a diagnostic, for example. */
@@ -4055,96 +3974,17 @@ finish_label_address_expr (tree label)
}
/* Hook used by expand_expr to expand language-specific tree codes. */
+/* The only things that should go here are bits needed to expand
+ constant initializers. Everything else should be handled by the
+ gimplification routines. */
rtx
-c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
+c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
int modifier /* Actually enum_modifier. */,
rtx *alt_rtl)
{
switch (TREE_CODE (exp))
{
- case STMT_EXPR:
- {
- tree rtl_expr;
- rtx result;
- bool preserve_result = false;
-
- if (STMT_EXPR_WARN_UNUSED_RESULT (exp) && target == const0_rtx)
- {
- tree stmt = STMT_EXPR_STMT (exp);
- tree scope;
-
- for (scope = COMPOUND_BODY (stmt);
- scope && TREE_CODE (scope) != SCOPE_STMT;
- scope = TREE_CHAIN (scope));
-
- if (scope && SCOPE_STMT_BLOCK (scope))
- warning ("%Hignoring return value of `%D', "
- "declared with attribute warn_unused_result",
- &expr_wfl_stack->location,
- BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope)));
- else
- warning ("%Hignoring return value of function "
- "declared with attribute warn_unused_result",
- &expr_wfl_stack->location);
- }
-
- /* Since expand_expr_stmt calls free_temp_slots after every
- expression statement, we must call push_temp_slots here.
- Otherwise, any temporaries in use now would be considered
- out-of-scope after the first EXPR_STMT from within the
- STMT_EXPR. */
- push_temp_slots ();
- rtl_expr = expand_start_stmt_expr (!STMT_EXPR_NO_SCOPE (exp));
-
- /* If we want the result of this expression, find the last
- EXPR_STMT in the COMPOUND_STMT and mark it as addressable. */
- if (target != const0_rtx
- && TREE_CODE (STMT_EXPR_STMT (exp)) == COMPOUND_STMT
- && TREE_CODE (COMPOUND_BODY (STMT_EXPR_STMT (exp))) == SCOPE_STMT)
- {
- tree expr = COMPOUND_BODY (STMT_EXPR_STMT (exp));
- tree last = TREE_CHAIN (expr);
-
- while (TREE_CHAIN (last))
- {
- expr = last;
- last = TREE_CHAIN (last);
- }
-
- if (TREE_CODE (last) == SCOPE_STMT
- && TREE_CODE (expr) == EXPR_STMT)
- {
- /* Otherwise, note that we want the value from the last
- expression. */
- TREE_ADDRESSABLE (expr) = 1;
- preserve_result = true;
- }
- }
-
- expand_stmt (STMT_EXPR_STMT (exp));
- expand_end_stmt_expr (rtl_expr);
-
- result = expand_expr_real (rtl_expr, target, tmode, modifier, alt_rtl);
- if (preserve_result && GET_CODE (result) == MEM)
- {
- if (GET_MODE (result) != BLKmode)
- result = copy_to_reg (result);
- else
- preserve_temp_slots (result);
- }
-
- /* If the statment-expression does not have a scope, then the
- new temporaries we created within it must live beyond the
- statement-expression. */
- if (STMT_EXPR_NO_SCOPE (exp))
- preserve_temp_slots (NULL_RTX);
-
- pop_temp_slots ();
- return result;
- }
- break;
-
case COMPOUND_LITERAL_EXPR:
{
/* Initialize the anonymous variable declared in the compound
@@ -4155,63 +3995,18 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
}
default:
- abort ();
- }
-
- abort ();
- return NULL;
-}
-
-/* Hook used by safe_from_p to handle language-specific tree codes. */
-
-int
-c_safe_from_p (rtx target, tree exp)
-{
- /* We can see statements here when processing the body of a
- statement-expression. For a declaration statement declaring a
- variable, look at the variable's initializer. */
- if (TREE_CODE (exp) == DECL_STMT)
- {
- tree decl = DECL_STMT_DECL (exp);
-
- if (TREE_CODE (decl) == VAR_DECL
- && DECL_INITIAL (decl)
- && !safe_from_p (target, DECL_INITIAL (decl), /*top_p=*/0))
- return 0;
+ gcc_unreachable ();
}
-
- /* For any statement, we must follow the statement-chain. */
- if (STATEMENT_CODE_P (TREE_CODE (exp)) && TREE_CHAIN (exp))
- return safe_from_p (target, TREE_CHAIN (exp), /*top_p=*/0);
-
- /* Assume everything else is safe. */
- return 1;
-}
-
-/* Hook used by unsafe_for_reeval to handle language-specific tree codes. */
-
-int
-c_common_unsafe_for_reeval (tree exp)
-{
- /* Statement expressions may not be reevaluated, likewise compound
- literals. */
- if (TREE_CODE (exp) == STMT_EXPR
- || TREE_CODE (exp) == COMPOUND_LITERAL_EXPR)
- return 2;
-
- /* Walk all other expressions. */
- return -1;
}
/* Hook used by staticp to handle language-specific tree codes. */
-int
+tree
c_staticp (tree exp)
{
- if (TREE_CODE (exp) == COMPOUND_LITERAL_EXPR
- && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp)))
- return 1;
- return 0;
+ return (TREE_CODE (exp) == COMPOUND_LITERAL_EXPR
+ && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp))
+ ? exp : NULL);
}
@@ -4228,25 +4023,27 @@ boolean_increment (enum tree_code code, tree arg)
switch (code)
{
case PREINCREMENT_EXPR:
- val = build (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
break;
case POSTINCREMENT_EXPR:
- val = build (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
arg = save_expr (arg);
- val = build (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
- val = build (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
break;
case PREDECREMENT_EXPR:
- val = build (MODIFY_EXPR, TREE_TYPE (arg), arg, invert_truthvalue (arg));
+ val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
+ invert_truthvalue (arg));
break;
case POSTDECREMENT_EXPR:
- val = build (MODIFY_EXPR, TREE_TYPE (arg), arg, invert_truthvalue (arg));
+ val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
+ invert_truthvalue (arg));
arg = save_expr (arg);
- val = build (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
- val = build (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
break;
default:
- abort ();
+ gcc_unreachable ();
}
TREE_SIDE_EFFECTS (val) = 1;
return val;
@@ -4261,16 +4058,18 @@ c_stddef_cpp_builtins(void)
builtin_define_with_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE, 0);
builtin_define_with_value ("__WCHAR_TYPE__", MODIFIED_WCHAR_TYPE, 0);
builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
+ builtin_define_with_value ("__INTMAX_TYPE__", INTMAX_TYPE, 0);
+ builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
}
static void
c_init_attributes (void)
{
/* Fill in the built_in_attributes array. */
-#define DEF_ATTR_NULL_TREE(ENUM) \
+#define DEF_ATTR_NULL_TREE(ENUM) \
built_in_attributes[(int) ENUM] = NULL_TREE;
-#define DEF_ATTR_INT(ENUM, VALUE) \
- built_in_attributes[(int) ENUM] = build_int_2 (VALUE, VALUE < 0 ? -1 : 0);
+#define DEF_ATTR_INT(ENUM, VALUE) \
+ built_in_attributes[(int) ENUM] = build_int_cst (NULL_TREE, VALUE);
#define DEF_ATTR_IDENT(ENUM, STRING) \
built_in_attributes[(int) ENUM] = get_identifier (STRING);
#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \
@@ -4291,39 +4090,31 @@ c_init_attributes (void)
struct attribute_spec.handler. */
static tree
-handle_packed_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
+handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
int flags, bool *no_add_attrs)
{
if (TYPE_P (*node))
{
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_type_copy (*node);
+ *node = build_variant_type_copy (*node);
TYPE_PACKED (*node) = 1;
- if (TYPE_MAIN_VARIANT (*node) == *node)
- {
- /* If it is the main variant, then pack the other variants
- too. This happens in,
-
- struct Foo {
- struct Foo const *ptr; // creates a variant w/o packed flag
- } __ attribute__((packed)); // packs it now.
- */
- tree probe;
-
- for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe))
- TYPE_PACKED (probe) = 1;
- }
-
}
else if (TREE_CODE (*node) == FIELD_DECL)
- DECL_PACKED (*node) = 1;
+ {
+ if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT)
+ warning (OPT_Wattributes,
+ "%qE attribute ignored for field of type %qT",
+ name, TREE_TYPE (*node));
+ else
+ DECL_PACKED (*node) = 1;
+ }
/* We can't set DECL_PACKED for a VAR_DECL, because the bit is
used for DECL_REGISTER. It wouldn't mean anything anyway.
We can't set DECL_PACKED on the type of a TYPE_DECL, because
that changes what the typedef is typing. */
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4335,14 +4126,14 @@ handle_packed_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
static tree
handle_nocommon_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == VAR_DECL)
DECL_COMMON (*node) = 0;
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4353,14 +4144,14 @@ handle_nocommon_attribute (tree *node, tree name,
struct attribute_spec.handler. */
static tree
-handle_common_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == VAR_DECL)
DECL_COMMON (*node) = 1;
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4371,8 +4162,8 @@ handle_common_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
struct attribute_spec.handler. */
static tree
-handle_noreturn_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree type = TREE_TYPE (*node);
@@ -4384,10 +4175,10 @@ handle_noreturn_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
TREE_TYPE (*node)
= build_pointer_type
(build_type_variant (TREE_TYPE (type),
- TREE_READONLY (TREE_TYPE (type)), 1));
+ TYPE_READONLY (TREE_TYPE (type)), 1));
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4399,14 +4190,14 @@ handle_noreturn_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
static tree
handle_noinline_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
DECL_UNINLINABLE (*node) = 1;
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4418,8 +4209,8 @@ handle_noinline_attribute (tree *node, tree name,
static tree
handle_always_inline_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
@@ -4429,19 +4220,64 @@ handle_always_inline_attribute (tree *node, tree name,
}
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
return NULL_TREE;
}
+/* Handle a "gnu_inline" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_gnu_inline_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
+ {
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "flatten" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_flatten_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ ;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+
/* Handle a "used" attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_used_attribute (tree *pnode, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree node = *pnode;
@@ -4449,10 +4285,11 @@ handle_used_attribute (tree *pnode, tree name, tree args ATTRIBUTE_UNUSED,
|| (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
{
TREE_USED (node) = 1;
+ DECL_PRESERVE_P (node) = 1;
}
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4463,8 +4300,8 @@ handle_used_attribute (tree *pnode, tree name, tree args ATTRIBUTE_UNUSED,
struct attribute_spec.handler. */
static tree
-handle_unused_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int flags, bool *no_add_attrs)
{
if (DECL_P (*node))
{
@@ -4478,26 +4315,56 @@ handle_unused_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
TREE_USED (decl) = 1;
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
}
else
{
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_type_copy (*node);
+ *node = build_variant_type_copy (*node);
TREE_USED (*node) = 1;
}
return NULL_TREE;
}
+/* Handle a "externally_visible" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_externally_visible_attribute (tree *pnode, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree node = *pnode;
+
+ if (TREE_CODE (node) == FUNCTION_DECL || TREE_CODE (node) == VAR_DECL)
+ {
+ if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL
+ && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node))
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute have effect only on public objects", name);
+ *no_add_attrs = true;
+ }
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "const" attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_const_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree type = TREE_TYPE (*node);
@@ -4512,7 +4379,7 @@ handle_const_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
TREE_THIS_VOLATILE (TREE_TYPE (type))));
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4524,42 +4391,46 @@ handle_const_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
static tree
handle_transparent_union_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED, int flags,
+ tree ARG_UNUSED (args), int flags,
bool *no_add_attrs)
{
- tree decl = NULL_TREE;
- tree *type = NULL;
- int is_type = 0;
+ tree type = NULL;
+
+ *no_add_attrs = true;
if (DECL_P (*node))
{
- decl = *node;
- type = &TREE_TYPE (decl);
- is_type = TREE_CODE (*node) == TYPE_DECL;
+ if (TREE_CODE (*node) != TYPE_DECL)
+ goto ignored;
+ node = &TREE_TYPE (*node);
+ type = *node;
}
else if (TYPE_P (*node))
- type = node, is_type = 1;
+ type = *node;
+ else
+ goto ignored;
- if (is_type
- && TREE_CODE (*type) == UNION_TYPE
- && (decl == 0
- || (TYPE_FIELDS (*type) != 0
- && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
+ if (TREE_CODE (type) == UNION_TYPE)
{
+ /* When IN_PLACE is set, leave the check for FIELDS and MODE to
+ the code in finish_struct. */
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
- TYPE_TRANSPARENT_UNION (*type) = 1;
- }
- else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
- && TREE_CODE (*type) == UNION_TYPE
- && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
- DECL_TRANSPARENT_UNION (decl) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
+ {
+ if (TYPE_FIELDS (type) == NULL_TREE
+ || TYPE_MODE (type) != DECL_MODE (TYPE_FIELDS (type)))
+ goto ignored;
+
+ /* A type variant isn't good enough, since we don't a cast
+ to such a type removed as a no-op. */
+ *node = type = build_duplicate_type (type);
+ }
+
+ TYPE_TRANSPARENT_UNION (type) = 1;
+ return NULL_TREE;
}
+ ignored:
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
return NULL_TREE;
}
@@ -4568,8 +4439,8 @@ handle_transparent_union_attribute (tree *node, tree name,
static tree
handle_constructor_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
@@ -4584,7 +4455,7 @@ handle_constructor_attribute (tree *node, tree name,
}
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4596,8 +4467,8 @@ handle_constructor_attribute (tree *node, tree name,
static tree
handle_destructor_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
@@ -4612,7 +4483,7 @@ handle_destructor_attribute (tree *node, tree name,
}
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -4623,15 +4494,15 @@ handle_destructor_attribute (tree *node, tree name,
struct attribute_spec.handler. */
static tree
-handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_mode_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree type = *node;
*no_add_attrs = true;
if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
else
{
int j;
@@ -4639,12 +4510,12 @@ handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
int len = strlen (p);
enum machine_mode mode = VOIDmode;
tree typefm;
- tree ptr_type;
+ bool valid_mode;
if (len > 4 && p[0] == '_' && p[1] == '_'
&& p[len - 1] == '_' && p[len - 2] == '_')
{
- char *newp = alloca (len - 1);
+ char *newp = (char *) alloca (len - 1);
strcpy (newp, &p[2]);
newp[len - 4] = '\0';
@@ -4653,11 +4524,11 @@ handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
/* Change this type to have a type with the specified mode.
First check for the special modes. */
- if (! strcmp (p, "byte"))
+ if (!strcmp (p, "byte"))
mode = byte_mode;
else if (!strcmp (p, "word"))
mode = word_mode;
- else if (! strcmp (p, "pointer"))
+ else if (!strcmp (p, "pointer"))
mode = ptr_mode;
else
for (j = 0; j < NUM_MACHINE_MODES; j++)
@@ -4668,76 +4539,107 @@ handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
}
if (mode == VOIDmode)
- error ("unknown machine mode `%s'", p);
- else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
- (mode, TREE_UNSIGNED (type))))
- error ("no data type for mode `%s'", p);
- else if ((TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- && !(*targetm.valid_pointer_mode) (mode))
- error ("invalid pointer mode `%s'", p);
- else
{
- /* If this is a vector, make sure we either have hardware
- support, or we can emulate it. */
- if (VECTOR_MODE_P (mode) && !vector_mode_valid_p (mode))
+ error ("unknown machine mode %qs", p);
+ return NULL_TREE;
+ }
+
+ valid_mode = false;
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_INT:
+ case MODE_PARTIAL_INT:
+ case MODE_FLOAT:
+ case MODE_DECIMAL_FLOAT:
+ valid_mode = targetm.scalar_mode_supported_p (mode);
+ break;
+
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ valid_mode = targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
+ break;
+
+ case MODE_VECTOR_INT:
+ case MODE_VECTOR_FLOAT:
+ warning (OPT_Wattributes, "specifying vector types with "
+ "__attribute__ ((mode)) is deprecated");
+ warning (OPT_Wattributes,
+ "use __attribute__ ((vector_size)) instead");
+ valid_mode = vector_mode_valid_p (mode);
+ break;
+
+ default:
+ break;
+ }
+ if (!valid_mode)
+ {
+ error ("unable to emulate %qs", p);
+ return NULL_TREE;
+ }
+
+ if (POINTER_TYPE_P (type))
+ {
+ tree (*fn)(tree, enum machine_mode, bool);
+
+ if (!targetm.valid_pointer_mode (mode))
{
- error ("unable to emulate '%s'", GET_MODE_NAME (mode));
+ error ("invalid pointer mode %qs", p);
return NULL_TREE;
}
if (TREE_CODE (type) == POINTER_TYPE)
+ fn = build_pointer_type_for_mode;
+ else
+ fn = build_reference_type_for_mode;
+ typefm = fn (TREE_TYPE (type), mode, false);
+ }
+ else
+ typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
+
+ if (typefm == NULL_TREE)
+ {
+ error ("no data type for mode %qs", p);
+ return NULL_TREE;
+ }
+ else if (TREE_CODE (type) == ENUMERAL_TYPE)
+ {
+ /* For enumeral types, copy the precision from the integer
+ type returned above. If not an INTEGER_TYPE, we can't use
+ this mode for this type. */
+ if (TREE_CODE (typefm) != INTEGER_TYPE)
{
- ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
- mode);
- *node = ptr_type;
- }
- else if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
- mode);
- *node = ptr_type;
+ error ("cannot use mode %qs for enumeral types", p);
+ return NULL_TREE;
}
- else if (TREE_CODE (type) == ENUMERAL_TYPE)
- {
- /* For enumeral types, copy the precision from the integer
- type returned above. If not an INTEGER_TYPE, we can't use
- this mode for this type. */
- if (TREE_CODE (typefm) != INTEGER_TYPE)
- {
- error ("cannot use mode %qs for enumeral types", p);
- return NULL_TREE;
- }
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- type = build_type_copy (type);
-
- /* We cannot use layout_type here, because that will attempt
- to re-layout all variants, corrupting our original. */
+ if (flags & ATTR_FLAG_TYPE_IN_PLACE)
+ {
TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
- TYPE_MIN_VALUE (type) = TYPE_MIN_VALUE (typefm);
- TYPE_MAX_VALUE (type) = TYPE_MAX_VALUE (typefm);
- TYPE_SIZE (type) = TYPE_SIZE (typefm);
- TYPE_SIZE_UNIT (type) = TYPE_SIZE_UNIT (typefm);
- TYPE_MODE (type) = TYPE_MODE (typefm);
- if (!TYPE_USER_ALIGN (type))
- TYPE_ALIGN (type) = TYPE_ALIGN (typefm);
-
- *node = type;
+ typefm = type;
}
- else if (VECTOR_MODE_P (mode)
- ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
- : TREE_CODE (type) != TREE_CODE (typefm))
-
+ else
{
- error ("mode `%s' applied to inappropriate type", p);
- return NULL_TREE;
+ /* We cannot build a type variant, as there's code that assumes
+ that TYPE_MAIN_VARIANT has the same mode. This includes the
+ debug generators. Instead, create a subrange type. This
+ results in all of the enumeral values being emitted only once
+ in the original, and the subtype gets them by reference. */
+ if (TYPE_UNSIGNED (type))
+ typefm = make_unsigned_type (TYPE_PRECISION (typefm));
+ else
+ typefm = make_signed_type (TYPE_PRECISION (typefm));
+ TREE_TYPE (typefm) = type;
}
- else
- *node = typefm;
-
- /* No need to layout the type here. The caller should do this. */
}
+ else if (VECTOR_MODE_P (mode)
+ ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
+ : TREE_CODE (type) != TREE_CODE (typefm))
+ {
+ error ("mode %qs applied to inappropriate type", p);
+ return NULL_TREE;
+ }
+
+ *node = typefm;
}
return NULL_TREE;
@@ -4747,23 +4649,25 @@ handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
struct attribute_spec.handler. */
static tree
-handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree decl = *node;
if (targetm.have_named_sections)
{
+ user_defined_section_attribute = true;
+
if ((TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& TREE_CODE (TREE_VALUE (args)) == STRING_CST)
{
if (TREE_CODE (decl) == VAR_DECL
&& current_function_decl != NULL_TREE
- && ! TREE_STATIC (decl))
+ && !TREE_STATIC (decl))
{
error ("%Jsection attribute cannot be specified for "
- "local variables", decl);
+ "local variables", decl);
*no_add_attrs = true;
}
@@ -4773,8 +4677,8 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
&& strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
{
- error ("%Jsection of '%D' conflicts with previous declaration",
- *node, *node);
+ error ("section of %q+D conflicts with previous declaration",
+ *node);
*no_add_attrs = true;
}
else
@@ -4782,7 +4686,7 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
}
else
{
- error ("%Jsection attribute not allowed for '%D'", *node, *node);
+ error ("section attribute not allowed for %q+D", *node);
*no_add_attrs = true;
}
}
@@ -4799,7 +4703,7 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
struct attribute_spec.handler. */
static tree
-handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
+handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
int flags, bool *no_add_attrs)
{
tree decl = NULL_TREE;
@@ -4818,12 +4722,6 @@ handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
else if (TYPE_P (*node))
type = node, is_type = 1;
- /* Strip any NOPs of any kind. */
- while (TREE_CODE (align_expr) == NOP_EXPR
- || TREE_CODE (align_expr) == CONVERT_EXPR
- || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
- align_expr = TREE_OPERAND (align_expr, 0);
-
if (TREE_CODE (align_expr) != INTEGER_CST)
{
error ("requested alignment is not a constant");
@@ -4847,14 +4745,14 @@ handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
&& DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
{
tree tt = TREE_TYPE (decl);
- *type = build_type_copy (*type);
+ *type = build_variant_type_copy (*type);
DECL_ORIGINAL_TYPE (decl) = tt;
TYPE_NAME (*type) = decl;
TREE_USED (*type) = TREE_USED (decl);
TREE_TYPE (decl) = *type;
}
else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
+ *type = build_variant_type_copy (*type);
TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
TYPE_USER_ALIGN (*type) = 1;
@@ -4862,7 +4760,7 @@ handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
else if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FIELD_DECL)
{
- error ("%Jalignment may not be specified for '%D'", decl, decl);
+ error ("alignment may not be specified for %q+D", decl);
*no_add_attrs = true;
}
else
@@ -4878,12 +4776,17 @@ handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
struct attribute_spec.handler. */
static tree
-handle_weak_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs ATTRIBUTE_UNUSED)
+handle_weak_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
{
- declare_weak (*node);
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ || TREE_CODE (*node) == VAR_DECL)
+ declare_weak (*node);
+ else
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+
return NULL_TREE;
}
@@ -4893,24 +4796,35 @@ handle_weak_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
static tree
handle_alias_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree decl = *node;
if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
- || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
- {
- error ("%J'%D' defined both normally and as an alias", decl, decl);
+ || (TREE_CODE (decl) != FUNCTION_DECL
+ && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
+ /* A static variable declaration is always a tentative definition,
+ but the alias is a non-tentative definition which overrides. */
+ || (TREE_CODE (decl) != FUNCTION_DECL
+ && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
+ {
+ error ("%q+D defined both normally and as an alias", decl);
*no_add_attrs = true;
}
- else if (decl_function_context (decl) == 0)
+
+ /* Note that the very first time we process a nested declaration,
+ decl_function_context will not be set. Indeed, *would* never
+ be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
+ we do below. After such frobbery, pushdecl would set the context.
+ In any case, this is never what we want. */
+ else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
{
tree id;
id = TREE_VALUE (args);
if (TREE_CODE (id) != STRING_CST)
{
- error ("alias arg not a string");
+ error ("alias argument not a string");
*no_add_attrs = true;
return NULL_TREE;
}
@@ -4921,12 +4835,65 @@ handle_alias_attribute (tree *node, tree name, tree args,
if (TREE_CODE (decl) == FUNCTION_DECL)
DECL_INITIAL (decl) = error_mark_node;
else
- DECL_EXTERNAL (decl) = 0;
+ {
+ if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+ DECL_EXTERNAL (decl) = 1;
+ else
+ DECL_EXTERNAL (decl) = 0;
+ TREE_STATIC (decl) = 1;
+ }
}
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "weakref" attribute; arguments as in struct
+ attribute_spec.handler. */
+
+static tree
+handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+ int flags, bool *no_add_attrs)
+{
+ tree attr = NULL_TREE;
+
+ /* We must ignore the attribute when it is associated with
+ local-scoped decls, since attribute alias is ignored and many
+ such symbols do not even have a DECL_WEAK field. */
+ if (decl_function_context (*node) || current_function_decl)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* The idea here is that `weakref("name")' mutates into `weakref,
+ alias("name")', and weakref without arguments, in turn,
+ implicitly adds weak. */
+
+ if (args)
+ {
+ attr = tree_cons (get_identifier ("alias"), args, attr);
+ attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr);
+
*no_add_attrs = true;
+
+ decl_attributes (node, attr, flags);
+ }
+ else
+ {
+ if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node)))
+ error ("%Jweakref attribute must appear before alias attribute",
+ *node);
+
+ /* Can't call declare_weak because it wants this to be TREE_PUBLIC,
+ and that isn't supported; and because it wants to add it to
+ the list of weak decls, which isn't helpful. */
+ DECL_WEAK (*node) = 1;
}
return NULL_TREE;
@@ -4937,76 +4904,169 @@ handle_alias_attribute (tree *node, tree name, tree args,
static tree
handle_visibility_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
+ int ARG_UNUSED (flags),
+ bool *ARG_UNUSED (no_add_attrs))
{
tree decl = *node;
tree id = TREE_VALUE (args);
+ enum symbol_visibility vis;
- *no_add_attrs = true;
-
- if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
+ if (TYPE_P (*node))
+ {
+ if (TREE_CODE (*node) == ENUMERAL_TYPE)
+ /* OK */;
+ else if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
+ name);
+ return NULL_TREE;
+ }
+ else if (TYPE_FIELDS (*node))
+ {
+ error ("%qE attribute ignored because %qT is already defined",
+ name, *node);
+ return NULL_TREE;
+ }
+ }
+ else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
return NULL_TREE;
}
if (TREE_CODE (id) != STRING_CST)
{
- error ("visibility arg not a string");
+ error ("visibility argument not a string");
return NULL_TREE;
}
+ /* If this is a type, set the visibility on the type decl. */
+ if (TYPE_P (decl))
+ {
+ decl = TYPE_NAME (decl);
+ if (!decl)
+ return NULL_TREE;
+ if (TREE_CODE (decl) == IDENTIFIER_NODE)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored on types",
+ name);
+ return NULL_TREE;
+ }
+ }
+
if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ vis = VISIBILITY_DEFAULT;
else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
- DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL;
+ vis = VISIBILITY_INTERNAL;
else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ vis = VISIBILITY_HIDDEN;
else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
- DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
+ vis = VISIBILITY_PROTECTED;
else
- error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+ {
+ error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+ vis = VISIBILITY_DEFAULT;
+ }
+
+ if (DECL_VISIBILITY_SPECIFIED (decl)
+ && vis != DECL_VISIBILITY (decl)
+ && lookup_attribute ("visibility", (TYPE_P (*node)
+ ? TYPE_ATTRIBUTES (*node)
+ : DECL_ATTRIBUTES (decl))))
+ error ("%qD redeclared with different visibility", decl);
+
+ DECL_VISIBILITY (decl) = vis;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+
+ /* Go ahead and attach the attribute to the node as well. This is needed
+ so we can determine whether we have VISIBILITY_DEFAULT because the
+ visibility was not specified, or because it was explicitly overridden
+ from the containing scope. */
return NULL_TREE;
}
+/* Determine the ELF symbol visibility for DECL, which is either a
+ variable or a function. It is an error to use this function if a
+ definition of DECL is not available in this translation unit.
+ Returns true if the final visibility has been determined by this
+ function; false if the caller is free to make additional
+ modifications. */
+
+bool
+c_determine_visibility (tree decl)
+{
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL);
+
+ /* If the user explicitly specified the visibility with an
+ attribute, honor that. DECL_VISIBILITY will have been set during
+ the processing of the attribute. We check for an explicit
+ attribute, rather than just checking DECL_VISIBILITY_SPECIFIED,
+ to distinguish the use of an attribute from the use of a "#pragma
+ GCC visibility push(...)"; in the latter case we still want other
+ considerations to be able to overrule the #pragma. */
+ if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
+ return true;
+
+ /* Anything that is exported must have default visibility. */
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+ {
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ return true;
+ }
+
+ /* Set default visibility to whatever the user supplied with
+ visibility_specified depending on #pragma GCC visibility. */
+ if (!DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ }
+ return false;
+}
+
/* Handle an "tls_model" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_tls_model_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
+ tree id;
tree decl = *node;
+ enum tls_model kind;
- if (! DECL_THREAD_LOCAL (decl))
+ *no_add_attrs = true;
+
+ if (!DECL_THREAD_LOCAL_P (decl))
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ return NULL_TREE;
}
- else
- {
- tree id;
- id = TREE_VALUE (args);
- if (TREE_CODE (id) != STRING_CST)
- {
- error ("tls_model arg not a string");
- *no_add_attrs = true;
- return NULL_TREE;
- }
- if (strcmp (TREE_STRING_POINTER (id), "local-exec")
- && strcmp (TREE_STRING_POINTER (id), "initial-exec")
- && strcmp (TREE_STRING_POINTER (id), "local-dynamic")
- && strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
- {
- error ("tls_model arg must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
- *no_add_attrs = true;
- return NULL_TREE;
- }
+ kind = DECL_TLS_MODEL (decl);
+ id = TREE_VALUE (args);
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("tls_model argument not a string");
+ return NULL_TREE;
}
+ if (!strcmp (TREE_STRING_POINTER (id), "local-exec"))
+ kind = TLS_MODEL_LOCAL_EXEC;
+ else if (!strcmp (TREE_STRING_POINTER (id), "initial-exec"))
+ kind = TLS_MODEL_INITIAL_EXEC;
+ else if (!strcmp (TREE_STRING_POINTER (id), "local-dynamic"))
+ kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
+ else if (!strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
+ kind = TLS_MODEL_GLOBAL_DYNAMIC;
+ else
+ error ("tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
+
+ DECL_TLS_MODEL (decl) = kind;
return NULL_TREE;
}
@@ -5015,20 +5075,20 @@ handle_tls_model_attribute (tree *node, tree name, tree args,
static tree
handle_no_instrument_function_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
if (TREE_CODE (decl) != FUNCTION_DECL)
{
- error ("%J'%E' attribute applies only to functions", decl, name);
+ error ("%J%qE attribute applies only to functions", decl, name);
*no_add_attrs = true;
}
else if (DECL_INITIAL (decl))
{
- error ("%Jcan't set '%E' attribute after definition", decl, name);
+ error ("%Jcan%'t set %qE attribute after definition", decl, name);
*no_add_attrs = true;
}
else
@@ -5041,15 +5101,33 @@ handle_no_instrument_function_attribute (tree *node, tree name,
struct attribute_spec.handler. */
static tree
-handle_malloc_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
- if (TREE_CODE (*node) == FUNCTION_DECL)
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
DECL_IS_MALLOC (*node) = 1;
- /* ??? TODO: Support types. */
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "returns_twice" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_IS_RETURNS_TWICE (*node) = 1;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -5061,20 +5139,20 @@ handle_malloc_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
static tree
handle_no_limit_stack_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
if (TREE_CODE (decl) != FUNCTION_DECL)
{
- error ("%J'%E' attribute applies only to functions", decl, name);
+ error ("%J%qE attribute applies only to functions", decl, name);
*no_add_attrs = true;
}
else if (DECL_INITIAL (decl))
{
- error ("%Jcan't set '%E' attribute after definition", decl, name);
+ error ("%Jcan%'t set %qE attribute after definition", decl, name);
*no_add_attrs = true;
}
else
@@ -5087,32 +5165,45 @@ handle_no_limit_stack_attribute (tree *node, tree name,
struct attribute_spec.handler. */
static tree
-handle_pure_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
DECL_IS_PURE (*node) = 1;
/* ??? TODO: Support types. */
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
return NULL_TREE;
}
+/* Handle a "no vops" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *ARG_UNUSED (no_add_attrs))
+{
+ gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ DECL_IS_NOVOPS (*node) = 1;
+ return NULL_TREE;
+}
+
/* Handle a "deprecated" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_deprecated_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED, int flags,
+ tree ARG_UNUSED (args), int flags,
bool *no_add_attrs)
{
tree type = NULL_TREE;
int warn = 0;
- const char *what = NULL;
+ tree what = NULL_TREE;
if (DECL_P (*node))
{
@@ -5131,7 +5222,7 @@ handle_deprecated_attribute (tree *node, tree name,
else if (TYPE_P (*node))
{
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_type_copy (*node);
+ *node = build_variant_type_copy (*node);
TREE_DEPRECATED (*node) = 1;
type = *node;
}
@@ -5144,52 +5235,44 @@ handle_deprecated_attribute (tree *node, tree name,
if (type && TYPE_NAME (type))
{
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- what = IDENTIFIER_POINTER (TYPE_NAME (*node));
+ what = TYPE_NAME (*node);
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_NAME (TYPE_NAME (type)))
- what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ what = DECL_NAME (TYPE_NAME (type));
}
if (what)
- warning ("`%s' attribute ignored for `%s'",
- IDENTIFIER_POINTER (name), what);
+ warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
else
- warning ("`%s' attribute ignored",
- IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
}
return NULL_TREE;
}
-/* Keep a list of vector type nodes we created in handle_vector_size_attribute,
- to prevent us from duplicating type nodes unnecessarily.
- The normal mechanism to prevent duplicates is to use type_hash_canon, but
- since we want to distinguish types that are essentially identical (except
- for their debug representation), we use a local list here. */
-static GTY(()) tree vector_type_node_list = 0;
-
/* Handle a "vector_size" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_vector_size_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED,
+ int ARG_UNUSED (flags),
bool *no_add_attrs)
{
unsigned HOST_WIDE_INT vecsize, nunits;
- enum machine_mode mode, orig_mode, new_mode;
- tree type = *node, new_type = NULL_TREE;
- tree type_list_node;
+ enum machine_mode orig_mode;
+ tree type = *node, new_type, size;
*no_add_attrs = true;
- if (! host_integerp (TREE_VALUE (args), 1))
+ size = TREE_VALUE (args);
+
+ if (!host_integerp (size, 1))
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
return NULL_TREE;
}
/* Get the vector size (in bytes). */
- vecsize = tree_low_cst (TREE_VALUE (args), 1);
+ vecsize = tree_low_cst (size, 1);
/* We need to provide for vector pointers, vector arrays, and
functions returning vectors. For example:
@@ -5209,100 +5292,38 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
orig_mode = TYPE_MODE (type);
if (TREE_CODE (type) == RECORD_TYPE
- || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == VECTOR_TYPE
+ || (!SCALAR_FLOAT_MODE_P (orig_mode)
&& GET_MODE_CLASS (orig_mode) != MODE_INT)
- || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
+ || !host_integerp (TYPE_SIZE_UNIT (type), 1))
{
- error ("invalid vector type for attribute `%s'",
- IDENTIFIER_POINTER (name));
+ error ("invalid vector type for attribute %qE", name);
return NULL_TREE;
}
- /* Calculate how many units fit in the vector. */
- nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
-
- /* Find a suitably sized vector. */
- new_mode = VOIDmode;
- for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
- ? MODE_VECTOR_INT
- : MODE_VECTOR_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (vecsize == GET_MODE_SIZE (mode)
- && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
- {
- new_mode = mode;
- break;
- }
-
- if (new_mode == VOIDmode)
+ if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
{
- error ("no vector mode with the size and type specified could be found");
- return NULL_TREE;
+ error ("vector size not an integral multiple of component size");
+ return NULL;
}
- for (type_list_node = vector_type_node_list; type_list_node;
- type_list_node = TREE_CHAIN (type_list_node))
+ if (vecsize == 0)
{
- tree other_type = TREE_VALUE (type_list_node);
- tree record = TYPE_DEBUG_REPRESENTATION_TYPE (other_type);
- tree fields = TYPE_FIELDS (record);
- tree field_type = TREE_TYPE (fields);
- tree array_type = TREE_TYPE (field_type);
- if (TREE_CODE (fields) != FIELD_DECL
- || TREE_CODE (field_type) != ARRAY_TYPE)
- abort ();
-
- if (TYPE_MODE (other_type) == mode && type == array_type)
- {
- new_type = other_type;
- break;
- }
+ error ("zero vector size");
+ return NULL;
}
- if (new_type == NULL_TREE)
+ /* Calculate how many units fit in the vector. */
+ nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+ if (nunits & (nunits - 1))
{
- tree index, array, rt, list_node;
-
- new_type = (*lang_hooks.types.type_for_mode) (new_mode,
- TREE_UNSIGNED (type));
-
- if (!new_type)
- {
- error ("no vector mode with the size and type specified could be found");
- return NULL_TREE;
- }
-
- new_type = build_type_copy (new_type);
-
- /* If this is a vector, make sure we either have hardware
- support, or we can emulate it. */
- if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
- || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
- && !vector_mode_valid_p (mode))
- {
- error ("unable to emulate '%s'", GET_MODE_NAME (mode));
- return NULL_TREE;
- }
-
- /* Set the debug information here, because this is the only
- place where we know the underlying type for a vector made
- with vector_size. For debugging purposes we pretend a vector
- is an array within a structure. */
- index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0);
- array = build_array_type (type, build_index_type (index));
- rt = make_node (RECORD_TYPE);
-
- TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
- DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
- layout_type (rt);
- TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt;
-
- list_node = build_tree_list (NULL, new_type);
- TREE_CHAIN (list_node) = vector_type_node_list;
- vector_type_node_list = list_node;
+ error ("number of components of the vector not a power of two");
+ return NULL_TREE;
}
+ new_type = build_vector_type (type, nunits);
+
/* Build back pointers if needed. */
*node = reconstruct_complex_type (*node, new_type);
@@ -5311,8 +5332,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
/* Handle the "nonnull" attribute. */
static tree
-handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
- tree args, int flags ATTRIBUTE_UNUSED,
+handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
+ tree args, int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree type = *node;
@@ -5321,12 +5342,12 @@ handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
/* If no arguments are specified, all pointer arguments should be
non-null. Verify a full prototype is given so that the arguments
will have the correct types when we actually check them later. */
- if (! args)
+ if (!args)
{
- if (! TYPE_ARG_TYPES (type))
+ if (!TYPE_ARG_TYPES (type))
{
error ("nonnull attribute without arguments on a non-prototype");
- *no_add_attrs = true;
+ *no_add_attrs = true;
}
return NULL_TREE;
}
@@ -5336,11 +5357,11 @@ handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
{
tree argument;
- unsigned HOST_WIDE_INT arg_num, ck_num;
+ unsigned HOST_WIDE_INT arg_num = 0, ck_num;
- if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
+ if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
{
- error ("nonnull argument has invalid operand number (arg %lu)",
+ error ("nonnull argument has invalid operand number (argument %lu)",
(unsigned long) attr_arg_num);
*no_add_attrs = true;
return NULL_TREE;
@@ -5351,23 +5372,23 @@ handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
{
for (ck_num = 1; ; ck_num++)
{
- if (! argument || ck_num == arg_num)
+ if (!argument || ck_num == arg_num)
break;
argument = TREE_CHAIN (argument);
}
- if (! argument
+ if (!argument
|| TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE)
{
- error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)",
+ error ("nonnull argument with out-of-range operand number (argument %lu, operand %lu)",
(unsigned long) attr_arg_num, (unsigned long) arg_num);
*no_add_attrs = true;
return NULL_TREE;
}
- if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
+ if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
{
- error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)",
+ error ("nonnull argument references non-pointer operand (argument %lu, operand %lu)",
(unsigned long) attr_arg_num, (unsigned long) arg_num);
*no_add_attrs = true;
return NULL_TREE;
@@ -5391,22 +5412,90 @@ check_function_nonnull (tree attrs, tree params)
{
if (is_attribute_p ("nonnull", TREE_PURPOSE (a)))
{
- args = TREE_VALUE (a);
+ args = TREE_VALUE (a);
- /* Walk the argument list. If we encounter an argument number we
- should check for non-null, do it. If the attribute has no args,
- then every pointer argument is checked (in which case the check
+ /* Walk the argument list. If we encounter an argument number we
+ should check for non-null, do it. If the attribute has no args,
+ then every pointer argument is checked (in which case the check
for pointer type is done in check_nonnull_arg). */
- for (param = params, param_num = 1; ;
- param_num++, param = TREE_CHAIN (param))
- {
- if (! param)
+ for (param = params, param_num = 1; ;
+ param_num++, param = TREE_CHAIN (param))
+ {
+ if (!param)
break;
- if (! args || nonnull_check_p (args, param_num))
+ if (!args || nonnull_check_p (args, param_num))
check_function_arguments_recurse (check_nonnull_arg, NULL,
TREE_VALUE (param),
param_num);
- }
+ }
+ }
+ }
+}
+
+/* Check that the Nth argument of a function call (counting backwards
+ from the end) is a (pointer)0. */
+
+static void
+check_function_sentinel (tree attrs, tree params, tree typelist)
+{
+ tree attr = lookup_attribute ("sentinel", attrs);
+
+ if (attr)
+ {
+ /* Skip over the named arguments. */
+ while (typelist && params)
+ {
+ typelist = TREE_CHAIN (typelist);
+ params = TREE_CHAIN (params);
+ }
+
+ if (typelist || !params)
+ warning (OPT_Wformat,
+ "not enough variable arguments to fit a sentinel");
+ else
+ {
+ tree sentinel, end;
+ unsigned pos = 0;
+
+ if (TREE_VALUE (attr))
+ {
+ tree p = TREE_VALUE (TREE_VALUE (attr));
+ pos = TREE_INT_CST_LOW (p);
+ }
+
+ sentinel = end = params;
+
+ /* Advance `end' ahead of `sentinel' by `pos' positions. */
+ while (pos > 0 && TREE_CHAIN (end))
+ {
+ pos--;
+ end = TREE_CHAIN (end);
+ }
+ if (pos > 0)
+ {
+ warning (OPT_Wformat,
+ "not enough variable arguments to fit a sentinel");
+ return;
+ }
+
+ /* Now advance both until we find the last parameter. */
+ while (TREE_CHAIN (end))
+ {
+ end = TREE_CHAIN (end);
+ sentinel = TREE_CHAIN (sentinel);
+ }
+
+ /* Validate the sentinel. */
+ if ((!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
+ || !integer_zerop (TREE_VALUE (sentinel)))
+ /* Although __null (in C++) is only an integer we allow it
+ nevertheless, as we are guaranteed that it's exactly
+ as wide as a pointer, and we don't want to force
+ users to cast the NULL they have written there.
+ We warn with -Wstrict-null-sentinel, though. */
+ && (warn_strict_null_sentinel
+ || null_node != TREE_VALUE (sentinel)))
+ warning (OPT_Wformat, "missing sentinel in function call");
}
}
}
@@ -5418,12 +5507,13 @@ check_function_nonnull (tree attrs, tree params)
static bool
nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
{
- unsigned HOST_WIDE_INT arg_num;
+ unsigned HOST_WIDE_INT arg_num = 0;
for (; args; args = TREE_CHAIN (args))
{
- if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
- abort ();
+ bool found = get_nonnull_operand (TREE_VALUE (args), &arg_num);
+
+ gcc_assert (found);
if (arg_num == param_num)
return true;
@@ -5436,7 +5526,7 @@ nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
via check_function_arguments_recurse. */
static void
-check_nonnull_arg (void *ctx ATTRIBUTE_UNUSED, tree param,
+check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
unsigned HOST_WIDE_INT param_num)
{
/* Just skip checking the argument if it's not a pointer. This can
@@ -5447,8 +5537,8 @@ check_nonnull_arg (void *ctx ATTRIBUTE_UNUSED, tree param,
return;
if (integer_zerop (param))
- warning ("null argument where non-null required (arg %lu)",
- (unsigned long) param_num);
+ warning (OPT_Wnonnull, "null argument where non-null required "
+ "(argument %lu)", (unsigned long) param_num);
}
/* Helper for nonnull attribute handling; fetch the operand number
@@ -5457,13 +5547,7 @@ check_nonnull_arg (void *ctx ATTRIBUTE_UNUSED, tree param,
static bool
get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
{
- /* Strip any conversions from the arg number and verify they
- are constants. */
- while (TREE_CODE (arg_num_expr) == NOP_EXPR
- || TREE_CODE (arg_num_expr) == CONVERT_EXPR
- || TREE_CODE (arg_num_expr) == NON_LVALUE_EXPR)
- arg_num_expr = TREE_OPERAND (arg_num_expr, 0);
-
+ /* Verify the arg number is a constant. */
if (TREE_CODE (arg_num_expr) != INTEGER_CST
|| TREE_INT_CST_HIGH (arg_num_expr) != 0)
return false;
@@ -5476,15 +5560,15 @@ get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
struct attribute_spec.handler. */
static tree
-handle_nothrow_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
TREE_NOTHROW (*node) = 1;
/* ??? TODO: Support types. */
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
@@ -5496,7 +5580,7 @@ handle_nothrow_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
static tree
handle_cleanup_attribute (tree *node, tree name, tree args,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree decl = *node;
tree cleanup_id, cleanup_decl;
@@ -5507,7 +5591,7 @@ handle_cleanup_attribute (tree *node, tree name, tree args,
we'd be missing too much, since we do have attribute constructor. */
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
return NULL_TREE;
}
@@ -5518,14 +5602,14 @@ handle_cleanup_attribute (tree *node, tree name, tree args,
cleanup_id = TREE_VALUE (args);
if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
{
- error ("cleanup arg not an identifier");
+ error ("cleanup argument not an identifier");
*no_add_attrs = true;
return NULL_TREE;
}
cleanup_decl = lookup_name (cleanup_id);
if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
{
- error ("cleanup arg not a function");
+ error ("cleanup argument not a function");
*no_add_attrs = true;
return NULL_TREE;
}
@@ -5540,22 +5624,71 @@ handle_cleanup_attribute (tree *node, tree name, tree args,
static tree
handle_warn_unused_result_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
{
/* Ignore the attribute for functions not returning any value. */
if (VOID_TYPE_P (TREE_TYPE (*node)))
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
return NULL_TREE;
}
+
+/* Handle a "sentinel" attribute. */
+
+static tree
+handle_sentinel_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ tree params = TYPE_ARG_TYPES (*node);
+
+ if (!params)
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute requires prototypes with named arguments", name);
+ *no_add_attrs = true;
+ }
+ else
+ {
+ while (TREE_CHAIN (params))
+ params = TREE_CHAIN (params);
+
+ if (VOID_TYPE_P (TREE_VALUE (params)))
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute only applies to variadic functions", name);
+ *no_add_attrs = true;
+ }
+ }
+
+ if (args)
+ {
+ tree position = TREE_VALUE (args);
+
+ if (TREE_CODE (position) != INTEGER_CST)
+ {
+ warning (0, "requested position is not an integer constant");
+ *no_add_attrs = true;
+ }
+ else
+ {
+ if (tree_int_cst_lt (position, integer_zero_node))
+ {
+ warning (0, "requested position is less than zero");
+ *no_add_attrs = true;
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
/* Check for valid arguments being passed to a function. */
void
-check_function_arguments (tree attrs, tree params)
+check_function_arguments (tree attrs, tree params, tree typelist)
{
/* Check for null being passed in a pointer argument that must be
non-null. We also need to do this if format checking is enabled. */
@@ -5565,8 +5698,11 @@ check_function_arguments (tree attrs, tree params)
/* Check for errors in format strings. */
+ if (warn_format || warn_missing_format_attribute)
+ check_function_format (attrs, params);
+
if (warn_format)
- check_function_format (NULL, attrs, params);
+ check_function_sentinel (attrs, params, typelist);
}
/* Generic argument checking recursion routine. PARAM is the argument to
@@ -5578,11 +5714,13 @@ check_function_arguments_recurse (void (*callback)
void *ctx, tree param,
unsigned HOST_WIDE_INT param_num)
{
- if (TREE_CODE (param) == NOP_EXPR)
+ if ((TREE_CODE (param) == NOP_EXPR || TREE_CODE (param) == CONVERT_EXPR)
+ && (TYPE_PRECISION (TREE_TYPE (param))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (param, 0)))))
{
/* Strip coercion. */
check_function_arguments_recurse (callback, ctx,
- TREE_OPERAND (param, 0), param_num);
+ TREE_OPERAND (param, 0), param_num);
return;
}
@@ -5609,14 +5747,9 @@ check_function_arguments_recurse (void (*callback)
/* Extract the argument number, which was previously checked
to be valid. */
format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
- while (TREE_CODE (format_num_expr) == NOP_EXPR
- || TREE_CODE (format_num_expr) == CONVERT_EXPR
- || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
- format_num_expr = TREE_OPERAND (format_num_expr, 0);
- if (TREE_CODE (format_num_expr) != INTEGER_CST
- || TREE_INT_CST_HIGH (format_num_expr) != 0)
- abort ();
+ gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST
+ && !TREE_INT_CST_HIGH (format_num_expr));
format_num = TREE_INT_CST_LOW (format_num_expr);
@@ -5644,9 +5777,9 @@ check_function_arguments_recurse (void (*callback)
{
/* Check both halves of the conditional expression. */
check_function_arguments_recurse (callback, ctx,
- TREE_OPERAND (param, 1), param_num);
+ TREE_OPERAND (param, 1), param_num);
check_function_arguments_recurse (callback, ctx,
- TREE_OPERAND (param, 2), param_num);
+ TREE_OPERAND (param, 2), param_num);
return;
}
@@ -5658,8 +5791,9 @@ check_function_arguments_recurse (void (*callback)
int
field_decl_cmp (const void *x_p, const void *y_p)
{
- const tree *const x = x_p;
- const tree *const y = y_p;
+ const tree *const x = (const tree *const) x_p;
+ const tree *const y = (const tree *const) y_p;
+
if (DECL_NAME (*x) == DECL_NAME (*y))
/* A nontype is "greater" than a type. */
return (TREE_CODE (*y) == TYPE_DECL) - (TREE_CODE (*x) == TYPE_DECL);
@@ -5683,8 +5817,8 @@ pointer operator in resort_data. */
static int
resort_field_decl_cmp (const void *x_p, const void *y_p)
{
- const tree *const x = x_p;
- const tree *const y = y_p;
+ const tree *const x = (const tree *const) x_p;
+ const tree *const y = (const tree *const) y_p;
if (DECL_NAME (*x) == DECL_NAME (*y))
/* A nontype is "greater" than a type. */
@@ -5708,205 +5842,634 @@ resort_field_decl_cmp (const void *x_p, const void *y_p)
void
resort_sorted_fields (void *obj,
- void *orig_obj ATTRIBUTE_UNUSED ,
- gt_pointer_operator new_value,
- void *cookie)
+ void * ARG_UNUSED (orig_obj),
+ gt_pointer_operator new_value,
+ void *cookie)
{
- struct sorted_fields_type *sf = obj;
+ struct sorted_fields_type *sf = (struct sorted_fields_type *) obj;
resort_data.new_value = new_value;
resort_data.cookie = cookie;
qsort (&sf->elts[0], sf->len, sizeof (tree),
- resort_field_decl_cmp);
+ resort_field_decl_cmp);
}
-/* Used by estimate_num_insns. Estimate number of instructions seen
- by given statement. */
-static tree
-c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
+/* Subroutine of c_parse_error.
+ Return the result of concatenating LHS and RHS. RHS is really
+ a string literal, its first character is indicated by RHS_START and
+ RHS_SIZE is its length (including the terminating NUL character).
+
+ The caller is responsible for deleting the returned pointer. */
+
+static char *
+catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
{
- int *count = data;
- tree x = *tp;
+ const int lhs_size = strlen (lhs);
+ char *result = XNEWVEC (char, lhs_size + rhs_size);
+ strncpy (result, lhs, lhs_size);
+ strncpy (result + lhs_size, rhs_start, rhs_size);
+ return result;
+}
+
+/* Issue the error given by GMSGID, indicating that it occurred before
+ TOKEN, which had the associated VALUE. */
+
+void
+c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
+{
+#define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
+
+ char *message = NULL;
- if (TYPE_P (x) || DECL_P (x))
+ if (token == CPP_EOF)
+ message = catenate_messages (gmsgid, " at end of input");
+ else if (token == CPP_CHAR || token == CPP_WCHAR)
{
- *walk_subtrees = 0;
- return NULL;
+ unsigned int val = TREE_INT_CST_LOW (value);
+ const char *const ell = (token == CPP_CHAR) ? "" : "L";
+ if (val <= UCHAR_MAX && ISGRAPH (val))
+ message = catenate_messages (gmsgid, " before %s'%c'");
+ else
+ message = catenate_messages (gmsgid, " before %s'\\x%x'");
+
+ error (message, ell, val);
+ free (message);
+ message = NULL;
}
- /* Assume that constants and references counts nothing. These should
- be majorized by amount of operations among them we count later
- and are common target of CSE and similar optimizations. */
- if (TREE_CODE_CLASS (TREE_CODE (x)) == 'c'
- || TREE_CODE_CLASS (TREE_CODE (x)) == 'r')
- return NULL;
- switch (TREE_CODE (x))
- {
- /* Recognize assignments of large structures and constructors of
- big arrays. */
- case MODIFY_EXPR:
- case CONSTRUCTOR:
- {
- HOST_WIDE_INT size;
+ else if (token == CPP_STRING || token == CPP_WSTRING)
+ message = catenate_messages (gmsgid, " before string constant");
+ else if (token == CPP_NUMBER)
+ message = catenate_messages (gmsgid, " before numeric constant");
+ else if (token == CPP_NAME)
+ {
+ message = catenate_messages (gmsgid, " before %qE");
+ error (message, value);
+ free (message);
+ message = NULL;
+ }
+ else if (token == CPP_PRAGMA)
+ message = catenate_messages (gmsgid, " before %<#pragma%>");
+ else if (token == CPP_PRAGMA_EOL)
+ message = catenate_messages (gmsgid, " before end of line");
+ else if (token < N_TTYPES)
+ {
+ message = catenate_messages (gmsgid, " before %qs token");
+ error (message, cpp_type2name (token));
+ free (message);
+ message = NULL;
+ }
+ else
+ error (gmsgid);
- size = int_size_in_bytes (TREE_TYPE (x));
+ if (message)
+ {
+ error (message);
+ free (message);
+ }
+#undef catenate_messages
+}
- if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO)
- *count += 10;
- else
- *count += ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES);
- }
+/* Walk a gimplified function and warn for functions whose return value is
+ ignored and attribute((warn_unused_result)) is set. This is done before
+ inlining, so we don't have to worry about that. */
+
+void
+c_warn_unused_result (tree *top_p)
+{
+ tree t = *top_p;
+ tree_stmt_iterator i;
+ tree fdecl, ftype;
+
+ switch (TREE_CODE (t))
+ {
+ case STATEMENT_LIST:
+ for (i = tsi_start (*top_p); !tsi_end_p (i); tsi_next (&i))
+ c_warn_unused_result (tsi_stmt_ptr (i));
break;
- case CALL_EXPR:
- {
- tree decl = get_callee_fndecl (x);
- if (decl && DECL_BUILT_IN (decl))
- switch (DECL_FUNCTION_CODE (decl))
- {
- case BUILT_IN_CONSTANT_P:
- *walk_subtrees = 0;
- return NULL_TREE;
- case BUILT_IN_EXPECT:
- return NULL_TREE;
- default:
- break;
- }
- *count += 10;
- break;
- }
- /* Few special cases of expensive operations. This is usefull
- to avoid inlining on functions having too many of these. */
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- case RDIV_EXPR:
- *count += 10;
+ case COND_EXPR:
+ c_warn_unused_result (&COND_EXPR_THEN (t));
+ c_warn_unused_result (&COND_EXPR_ELSE (t));
break;
- /* Various containers that will produce no code themselves. */
- case INIT_EXPR:
- case TARGET_EXPR:
case BIND_EXPR:
- case BLOCK:
- case TREE_LIST:
- case TREE_VEC:
- case IDENTIFIER_NODE:
- case PLACEHOLDER_EXPR:
- case WITH_CLEANUP_EXPR:
- case CLEANUP_POINT_EXPR:
- case NOP_EXPR:
- case VIEW_CONVERT_EXPR:
- case SAVE_EXPR:
- case UNSAVE_EXPR:
- case COMPLEX_EXPR:
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- case TRY_CATCH_EXPR:
+ c_warn_unused_result (&BIND_EXPR_BODY (t));
+ break;
case TRY_FINALLY_EXPR:
- case LABEL_EXPR:
- case EXIT_EXPR:
- case LABELED_BLOCK_EXPR:
- case EXIT_BLOCK_EXPR:
- case EXPR_WITH_FILE_LOCATION:
-
- case EXPR_STMT:
- case COMPOUND_STMT:
- case RETURN_STMT:
- case LABEL_STMT:
- case SCOPE_STMT:
- case FILE_STMT:
- case CASE_LABEL:
- case STMT_EXPR:
- case CLEANUP_STMT:
-
- case SIZEOF_EXPR:
- case ARROW_EXPR:
- case ALIGNOF_EXPR:
+ case TRY_CATCH_EXPR:
+ c_warn_unused_result (&TREE_OPERAND (t, 0));
+ c_warn_unused_result (&TREE_OPERAND (t, 1));
+ break;
+ case CATCH_EXPR:
+ c_warn_unused_result (&CATCH_BODY (t));
+ break;
+ case EH_FILTER_EXPR:
+ c_warn_unused_result (&EH_FILTER_FAILURE (t));
+ break;
+
+ case CALL_EXPR:
+ if (TREE_USED (t))
+ break;
+
+ /* This is a naked call, as opposed to a CALL_EXPR nested inside
+ a MODIFY_EXPR. All calls whose value is ignored should be
+ represented like this. Look for the attribute. */
+ fdecl = get_callee_fndecl (t);
+ if (fdecl)
+ ftype = TREE_TYPE (fdecl);
+ else
+ {
+ ftype = TREE_TYPE (TREE_OPERAND (t, 0));
+ /* Look past pointer-to-function to the function type itself. */
+ ftype = TREE_TYPE (ftype);
+ }
+
+ if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
+ {
+ if (fdecl)
+ warning (0, "%Hignoring return value of %qD, "
+ "declared with attribute warn_unused_result",
+ EXPR_LOCUS (t), fdecl);
+ else
+ warning (0, "%Hignoring return value of function "
+ "declared with attribute warn_unused_result",
+ EXPR_LOCUS (t));
+ }
+ break;
+
+ default:
+ /* Not a container, not a call, or a call whose value is used. */
+ break;
+ }
+}
+
+/* Convert a character from the host to the target execution character
+ set. cpplib handles this, mostly. */
+
+HOST_WIDE_INT
+c_common_to_target_charset (HOST_WIDE_INT c)
+{
+ /* Character constants in GCC proper are sign-extended under -fsigned-char,
+ zero-extended under -fno-signed-char. cpplib insists that characters
+ and character constants are always unsigned. Hence we must convert
+ back and forth. */
+ cppchar_t uc = ((cppchar_t)c) & ((((cppchar_t)1) << CHAR_BIT)-1);
+
+ uc = cpp_host_to_exec_charset (parse_in, uc);
+
+ if (flag_signed_char)
+ return ((HOST_WIDE_INT)uc) << (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE)
+ >> (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE);
+ else
+ return uc;
+}
+
+/* Build the result of __builtin_offsetof. EXPR is a nested sequence of
+ component references, with STOP_REF, or alternatively an INDIRECT_REF of
+ NULL, at the bottom; much like the traditional rendering of offsetof as a
+ macro. Returns the folded and properly cast result. */
+
+static tree
+fold_offsetof_1 (tree expr, tree stop_ref)
+{
+ enum tree_code code = PLUS_EXPR;
+ tree base, off, t;
+
+ if (expr == stop_ref && TREE_CODE (expr) != ERROR_MARK)
+ return size_zero_node;
+
+ switch (TREE_CODE (expr))
+ {
+ case ERROR_MARK:
+ return expr;
+
+ case VAR_DECL:
+ error ("cannot apply %<offsetof%> to static data member %qD", expr);
+ return error_mark_node;
+
+ case CALL_EXPR:
+ error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
+ return error_mark_node;
+
+ case INTEGER_CST:
+ gcc_assert (integer_zerop (expr));
+ return size_zero_node;
+
+ case NOP_EXPR:
+ case INDIRECT_REF:
+ base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
+ gcc_assert (base == error_mark_node || base == size_zero_node);
+ return base;
+
+ case COMPONENT_REF:
+ base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
+ if (base == error_mark_node)
+ return base;
+
+ t = TREE_OPERAND (expr, 1);
+ if (DECL_C_BIT_FIELD (t))
+ {
+ error ("attempt to take address of bit-field structure "
+ "member %qD", t);
+ return error_mark_node;
+ }
+ off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
+ size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
+ / BITS_PER_UNIT));
+ break;
+
+ case ARRAY_REF:
+ base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
+ if (base == error_mark_node)
+ return base;
+
+ t = TREE_OPERAND (expr, 1);
+ if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
+ {
+ code = MINUS_EXPR;
+ t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
+ }
+ t = convert (sizetype, t);
+ off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+ break;
+
+ case COMPOUND_EXPR:
+ /* Handle static members of volatile structs. */
+ t = TREE_OPERAND (expr, 1);
+ gcc_assert (TREE_CODE (t) == VAR_DECL);
+ return fold_offsetof_1 (t, stop_ref);
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return size_binop (code, base, off);
+}
+
+tree
+fold_offsetof (tree expr, tree stop_ref)
+{
+ /* Convert back from the internal sizetype to size_t. */
+ return convert (size_type_node, fold_offsetof_1 (expr, stop_ref));
+}
+
+/* Print an error message for an invalid lvalue. USE says
+ how the lvalue is being used and so selects the error message. */
+
+void
+lvalue_error (enum lvalue_use use)
+{
+ switch (use)
+ {
+ case lv_assign:
+ error ("lvalue required as left operand of assignment");
+ break;
+ case lv_increment:
+ error ("lvalue required as increment operand");
+ break;
+ case lv_decrement:
+ error ("lvalue required as decrement operand");
break;
- case DECL_STMT:
- /* Do not account static initializers. */
- if (TREE_STATIC (TREE_OPERAND (x, 0)))
- *walk_subtrees = 0;
+ case lv_addressof:
+ error ("lvalue required as unary %<&%> operand");
+ break;
+ case lv_asm:
+ error ("lvalue required in asm statement");
break;
default:
- (*count)++;
+ gcc_unreachable ();
}
- return NULL;
}
+
+/* *PTYPE is an incomplete array. Complete it with a domain based on
+ INITIAL_VALUE. If INITIAL_VALUE is not present, use 1 if DO_DEFAULT
+ is true. Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
+ 2 if INITIAL_VALUE was NULL, and 3 if INITIAL_VALUE was empty. */
-/* Estimate number of instructions that will be created by expanding the body. */
int
-c_estimate_num_insns (tree decl)
+complete_array_type (tree *ptype, tree initial_value, bool do_default)
+{
+ tree maxindex, type, main_type, elt, unqual_elt;
+ int failure = 0, quals;
+
+ maxindex = size_zero_node;
+ if (initial_value)
+ {
+ if (TREE_CODE (initial_value) == STRING_CST)
+ {
+ int eltsize
+ = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
+ maxindex = size_int (TREE_STRING_LENGTH (initial_value)/eltsize - 1);
+ }
+ else if (TREE_CODE (initial_value) == CONSTRUCTOR)
+ {
+ VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
+
+ if (VEC_empty (constructor_elt, v))
+ {
+ if (pedantic)
+ failure = 3;
+ maxindex = integer_minus_one_node;
+ }
+ else
+ {
+ tree curindex;
+ unsigned HOST_WIDE_INT cnt;
+ constructor_elt *ce;
+
+ if (VEC_index (constructor_elt, v, 0)->index)
+ maxindex = fold_convert (sizetype,
+ VEC_index (constructor_elt,
+ v, 0)->index);
+ curindex = maxindex;
+
+ for (cnt = 1;
+ VEC_iterate (constructor_elt, v, cnt, ce);
+ cnt++)
+ {
+ if (ce->index)
+ curindex = fold_convert (sizetype, ce->index);
+ else
+ curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
+
+ if (tree_int_cst_lt (maxindex, curindex))
+ maxindex = curindex;
+ }
+ }
+ }
+ else
+ {
+ /* Make an error message unless that happened already. */
+ if (initial_value != error_mark_node)
+ failure = 1;
+ }
+ }
+ else
+ {
+ failure = 2;
+ if (!do_default)
+ return failure;
+ }
+
+ type = *ptype;
+ elt = TREE_TYPE (type);
+ quals = TYPE_QUALS (strip_array_types (elt));
+ if (quals == 0)
+ unqual_elt = elt;
+ else
+ unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+
+ /* Using build_distinct_type_copy and modifying things afterward instead
+ of using build_array_type to create a new type preserves all of the
+ TYPE_LANG_FLAG_? bits that the front end may have set. */
+ main_type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+ TREE_TYPE (main_type) = unqual_elt;
+ TYPE_DOMAIN (main_type) = build_index_type (maxindex);
+ layout_type (main_type);
+
+ if (quals == 0)
+ type = main_type;
+ else
+ type = c_build_qualified_type (main_type, quals);
+
+ *ptype = type;
+ return failure;
+}
+
+
+/* Used to help initialize the builtin-types.def table. When a type of
+ the correct size doesn't exist, use error_mark_node instead of NULL.
+ The later results in segfaults even when a decl using the type doesn't
+ get invoked. */
+
+tree
+builtin_type_for_size (int size, bool unsignedp)
+{
+ tree type = lang_hooks.types.type_for_size (size, unsignedp);
+ return type ? type : error_mark_node;
+}
+
+/* A helper function for resolve_overloaded_builtin in resolving the
+ overloaded __sync_ builtins. Returns a positive power of 2 if the
+ first operand of PARAMS is a pointer to a supported data type.
+ Returns 0 if an error is encountered. */
+
+static int
+sync_resolve_size (tree function, tree params)
{
- int num = 0;
- walk_tree_without_duplicates (&DECL_SAVED_TREE (decl), c_estimate_num_insns_1, &num);
- return num;
+ tree type;
+ int size;
+
+ if (params == NULL)
+ {
+ error ("too few arguments to function %qE", function);
+ return 0;
+ }
+
+ type = TREE_TYPE (TREE_VALUE (params));
+ if (TREE_CODE (type) != POINTER_TYPE)
+ goto incompatible;
+
+ type = TREE_TYPE (type);
+ if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+ goto incompatible;
+
+ size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+ if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
+ return size;
+
+ incompatible:
+ error ("incompatible type for argument %d of %qE", 1, function);
+ return 0;
+}
+
+/* A helper function for resolve_overloaded_builtin. Adds casts to
+ PARAMS to make arguments match up with those of FUNCTION. Drops
+ the variadic arguments at the end. Returns false if some error
+ was encountered; true on success. */
+
+static bool
+sync_resolve_params (tree orig_function, tree function, tree params)
+{
+ tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
+ tree ptype;
+ int number;
+
+ /* We've declared the implementation functions to use "volatile void *"
+ as the pointer parameter, so we shouldn't get any complaints from the
+ call to check_function_arguments what ever type the user used. */
+ arg_types = TREE_CHAIN (arg_types);
+ ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+ number = 2;
+
+ /* For the rest of the values, we need to cast these to FTYPE, so that we
+ don't get warnings for passing pointer types, etc. */
+ while (arg_types != void_list_node)
+ {
+ tree val;
+
+ params = TREE_CHAIN (params);
+ if (params == NULL)
+ {
+ error ("too few arguments to function %qE", orig_function);
+ return false;
+ }
+
+ /* ??? Ideally for the first conversion we'd use convert_for_assignment
+ so that we get warnings for anything that doesn't match the pointer
+ type. This isn't portable across the C and C++ front ends atm. */
+ val = TREE_VALUE (params);
+ val = convert (ptype, val);
+ val = convert (TREE_VALUE (arg_types), val);
+ TREE_VALUE (params) = val;
+
+ arg_types = TREE_CHAIN (arg_types);
+ number++;
+ }
+
+ /* The definition of these primitives is variadic, with the remaining
+ being "an optional list of variables protected by the memory barrier".
+ No clue what that's supposed to mean, precisely, but we consider all
+ call-clobbered variables to be protected so we're safe. */
+ TREE_CHAIN (params) = NULL;
+
+ return true;
}
-/* Used by c_decl_uninit to find where expressions like x = x + 1; */
+/* A helper function for resolve_overloaded_builtin. Adds a cast to
+ RESULT to make it match the type of the first pointer argument in
+ PARAMS. */
static tree
-c_decl_uninit_1 (tree *t, int *walk_sub_trees, void *x)
+sync_resolve_return (tree params, tree result)
{
- /* If x = EXP(&x)EXP, then do not warn about the use of x. */
- if (TREE_CODE (*t) == ADDR_EXPR && TREE_OPERAND (*t, 0) == x)
+ tree ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+ ptype = TYPE_MAIN_VARIANT (ptype);
+ return convert (ptype, result);
+}
+
+/* Some builtin functions are placeholders for other expressions. This
+ function should be called immediately after parsing the call expression
+ before surrounding code has committed to the type of the expression.
+
+ FUNCTION is the DECL that has been invoked; it is known to be a builtin.
+ PARAMS is the argument list for the call. The return value is non-null
+ when expansion is complete, and null if normal processing should
+ continue. */
+
+tree
+resolve_overloaded_builtin (tree function, tree params)
+{
+ enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
+ switch (DECL_BUILT_IN_CLASS (function))
{
- *walk_sub_trees = 0;
+ case BUILT_IN_NORMAL:
+ break;
+ case BUILT_IN_MD:
+ if (targetm.resolve_overloaded_builtin)
+ return targetm.resolve_overloaded_builtin (function, params);
+ else
+ return NULL_TREE;
+ default:
return NULL_TREE;
}
- if (*t == x)
- return *t;
- return NULL_TREE;
-}
-/* Find out if a variable is uninitialized based on DECL_INITIAL. */
+ /* Handle BUILT_IN_NORMAL here. */
+ switch (orig_code)
+ {
+ case BUILT_IN_FETCH_AND_ADD_N:
+ case BUILT_IN_FETCH_AND_SUB_N:
+ case BUILT_IN_FETCH_AND_OR_N:
+ case BUILT_IN_FETCH_AND_AND_N:
+ case BUILT_IN_FETCH_AND_XOR_N:
+ case BUILT_IN_FETCH_AND_NAND_N:
+ case BUILT_IN_ADD_AND_FETCH_N:
+ case BUILT_IN_SUB_AND_FETCH_N:
+ case BUILT_IN_OR_AND_FETCH_N:
+ case BUILT_IN_AND_AND_FETCH_N:
+ case BUILT_IN_XOR_AND_FETCH_N:
+ case BUILT_IN_NAND_AND_FETCH_N:
+ case BUILT_IN_BOOL_COMPARE_AND_SWAP_N:
+ case BUILT_IN_VAL_COMPARE_AND_SWAP_N:
+ case BUILT_IN_LOCK_TEST_AND_SET_N:
+ case BUILT_IN_LOCK_RELEASE_N:
+ {
+ int n = sync_resolve_size (function, params);
+ tree new_function, result;
+
+ if (n == 0)
+ return error_mark_node;
+
+ new_function = built_in_decls[orig_code + exact_log2 (n) + 1];
+ if (!sync_resolve_params (function, new_function, params))
+ return error_mark_node;
+ result = build_function_call (new_function, params);
+ if (orig_code != BUILT_IN_BOOL_COMPARE_AND_SWAP_N
+ && orig_code != BUILT_IN_LOCK_RELEASE_N)
+ result = sync_resolve_return (params, result);
+
+ return result;
+ }
+
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* Ignoring their sign, return true if two scalar types are the same. */
bool
-c_decl_uninit (tree t)
+same_scalar_type_ignoring_signedness (tree t1, tree t2)
{
- /* int x = x; is GCC extension to turn off this warning, only if warn_init_self is zero. */
- if (DECL_INITIAL (t) == t)
- return warn_init_self ? true : false;
+ enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2);
- /* Walk the trees looking for the variable itself. */
- if (walk_tree_without_duplicates (&DECL_INITIAL (t), c_decl_uninit_1, t))
- return true;
- return false;
+ gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE)
+ && (c2 == INTEGER_TYPE || c2 == REAL_TYPE));
+
+ /* Equality works here because c_common_signed_type uses
+ TYPE_MAIN_VARIANT. */
+ return lang_hooks.types.signed_type (t1)
+ == lang_hooks.types.signed_type (t2);
}
-/* Issue the error given by MSGID, indicating that it occurred before
- TOKEN, which had the associated VALUE. */
+/* Check for missing format attributes on function pointers. LTYPE is
+ the new type or left-hand side type. RTYPE is the old type or
+ right-hand side type. Returns TRUE if LTYPE is missing the desired
+ attribute. */
-void
-c_parse_error (const char *msgid, enum cpp_ttype token, tree value)
+bool
+check_missing_format_attribute (tree ltype, tree rtype)
{
- const char *string = _(msgid);
+ tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype);
+ tree ra;
- if (token == CPP_EOF)
- error ("%s at end of input", string);
- else if (token == CPP_CHAR || token == CPP_WCHAR)
+ for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
+ if (is_attribute_p ("format", TREE_PURPOSE (ra)))
+ break;
+ if (ra)
{
- unsigned int val = TREE_INT_CST_LOW (value);
- const char *const ell = (token == CPP_CHAR) ? "" : "L";
- if (val <= UCHAR_MAX && ISGRAPH (val))
- error ("%s before %s'%c'", string, ell, val);
- else
- error ("%s before %s'\\x%x'", string, ell, val);
+ tree la;
+ for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
+ if (is_attribute_p ("format", TREE_PURPOSE (la)))
+ break;
+ return !la;
}
- else if (token == CPP_STRING
- || token == CPP_WSTRING)
- error ("%s before string constant", string);
- else if (token == CPP_NUMBER)
- error ("%s before numeric constant", string);
- else if (token == CPP_NAME)
- error ("%s before \"%s\"", string, IDENTIFIER_POINTER (value));
- else if (token < N_TTYPES)
- error ("%s before '%s' token", string, cpp_type2name (token));
else
- error ("%s", string);
+ return false;
}
+/* Subscripting with type char is likely to lose on a machine where
+ chars are signed. So warn on any machine, but optionally. Don't
+ warn for unsigned char since that type is safe. Don't warn for
+ signed char because anyone who uses that must have done so
+ deliberately. Furthermore, we reduce the false positive load by
+ warning only for non-constant value of type char. */
+
+void
+warn_array_subscript_with_type_char (tree index)
+{
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node
+ && TREE_CODE (index) != INTEGER_CST)
+ warning (OPT_Wchar_subscripts, "array subscript has type %<char%>");
+}
+
+
#include "gt-c-common.h"
diff --git a/contrib/gcc/c-common.h b/contrib/gcc/c-common.h
index 3466bff..633990a 100644
--- a/contrib/gcc/c-common.h
+++ b/contrib/gcc/c-common.h
@@ -1,6 +1,6 @@
/* Definitions for c-common.c.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef GCC_C_COMMON_H
#define GCC_C_COMMON_H
@@ -27,21 +27,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
/* Usage of TREE_LANG_FLAG_?:
- 0: COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
- TREE_NEGATED_INT (in INTEGER_CST).
+ 0: TREE_NEGATED_INT (in INTEGER_CST).
IDENTIFIER_MARKED (used by search routines).
- SCOPE_BEGIN_P (in SCOPE_STMT)
DECL_PRETTY_FUNCTION_P (in VAR_DECL)
- NEW_FOR_SCOPE_P (in FOR_STMT)
- ASM_INPUT_P (in ASM_STMT)
- STMT_EXPR_NO_SCOPE (in STMT_EXPR)
1: C_DECLARED_LABEL_FLAG (in LABEL_DECL)
- STMT_IS_FULL_EXPR_P (in _STMT)
- 2: STMT_LINENO_FOR_FN_P (in _STMT)
- 3: SCOPE_NO_CLEANUPS_P (in SCOPE_STMT)
- COMPOUND_STMT_BODY_BLOCK (in COMPOUND_STMT)
- STMT_EXPR_WARN_UNUSED_RESULT (in STMT_EXPR)
- 4: SCOPE_PARTIAL_P (in SCOPE_STMT)
+ STATEMENT_LIST_STMT_EXPR (in STATEMENT_LIST)
+ 2: unused
+ 3: STATEMENT_LIST_HAS_LABEL (in STATEMENT_LIST)
+ 4: unused
*/
/* Reserved identifiers. This is the union of all the keywords for C,
@@ -77,8 +70,9 @@ enum rid
/* C extensions */
RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG,
- RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_PTRBASE,
- RID_PTREXTENT, RID_PTRVALUE, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P,
+ RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR,
+ RID_TYPES_COMPATIBLE_P,
+ RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
/* Too many ways of getting the name of a function as a string */
RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME,
@@ -88,19 +82,19 @@ enum rid
RID_PUBLIC, RID_PRIVATE, RID_PROTECTED,
RID_TEMPLATE, RID_NULL, RID_CATCH,
RID_DELETE, RID_FALSE, RID_NAMESPACE,
- RID_NEW, RID_OFFSETOF, RID_OPERATOR,
- RID_THIS, RID_THROW, RID_TRUE,
- RID_TRY, RID_TYPENAME, RID_TYPEID,
+ RID_NEW, RID_OFFSETOF, RID_OPERATOR,
+ RID_THIS, RID_THROW, RID_TRUE,
+ RID_TRY, RID_TYPENAME, RID_TYPEID,
RID_USING,
/* casts */
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
/* Objective-C */
- RID_ID, RID_AT_ENCODE, RID_AT_END,
+ RID_AT_ENCODE, RID_AT_END,
RID_AT_CLASS, RID_AT_ALIAS, RID_AT_DEFS,
RID_AT_PRIVATE, RID_AT_PROTECTED, RID_AT_PUBLIC,
- RID_AT_PROTOCOL, RID_AT_SELECTOR,
+ RID_AT_PROTOCOL, RID_AT_SELECTOR,
RID_AT_THROW, RID_AT_TRY, RID_AT_CATCH,
RID_AT_FINALLY, RID_AT_SYNCHRONIZED,
RID_AT_INTERFACE,
@@ -118,16 +112,16 @@ enum rid
};
#define OBJC_IS_AT_KEYWORD(rid) \
- ((unsigned int)(rid) >= (unsigned int)RID_FIRST_AT && \
- (unsigned int)(rid) <= (unsigned int)RID_LAST_AT)
+ ((unsigned int) (rid) >= (unsigned int) RID_FIRST_AT && \
+ (unsigned int) (rid) <= (unsigned int) RID_LAST_AT)
#define OBJC_IS_PQ_KEYWORD(rid) \
- ((unsigned int)(rid) >= (unsigned int)RID_FIRST_PQ && \
- (unsigned int)(rid) <= (unsigned int)RID_LAST_PQ)
+ ((unsigned int) (rid) >= (unsigned int) RID_FIRST_PQ && \
+ (unsigned int) (rid) <= (unsigned int) RID_LAST_PQ)
/* The elements of `ridpointers' are identifier nodes for the reserved
type names and storage classes. It is indexed by a RID_... value. */
-extern GTY ((length ("(int)RID_MAX"))) tree *ridpointers;
+extern GTY ((length ("(int) RID_MAX"))) tree *ridpointers;
/* Standard named or nameless data types of the C compiler. */
@@ -157,19 +151,16 @@ enum c_tree_index
CTI_DEFAULT_FUNCTION_TYPE,
- CTI_G77_INTEGER_TYPE,
- CTI_G77_UINTEGER_TYPE,
- CTI_G77_LONGINT_TYPE,
- CTI_G77_ULONGINT_TYPE,
-
/* These are not types, but we have to look them up all the time. */
CTI_FUNCTION_NAME_DECL,
CTI_PRETTY_FUNCTION_NAME_DECL,
CTI_C99_FUNCTION_NAME_DECL,
CTI_SAVED_FUNCTION_NAME_DECLS,
-
+
CTI_VOID_ZERO,
+ CTI_NULL,
+
CTI_MAX
};
@@ -206,12 +197,6 @@ struct c_common_identifier GTY(())
#define default_function_type c_global_trees[CTI_DEFAULT_FUNCTION_TYPE]
-/* g77 integer types, which which must be kept in sync with f/com.h */
-#define g77_integer_type_node c_global_trees[CTI_G77_INTEGER_TYPE]
-#define g77_uinteger_type_node c_global_trees[CTI_G77_UINTEGER_TYPE]
-#define g77_longint_type_node c_global_trees[CTI_G77_LONGINT_TYPE]
-#define g77_ulongint_type_node c_global_trees[CTI_G77_ULONGINT_TYPE]
-
#define function_name_decl_node c_global_trees[CTI_FUNCTION_NAME_DECL]
#define pretty_function_name_decl_node c_global_trees[CTI_PRETTY_FUNCTION_NAME_DECL]
#define c99_function_name_decl_node c_global_trees[CTI_C99_FUNCTION_NAME_DECL]
@@ -220,6 +205,9 @@ struct c_common_identifier GTY(())
/* A node for `((void) 0)'. */
#define void_zero_node c_global_trees[CTI_VOID_ZERO]
+/* The node for C++ `__null'. */
+#define null_node c_global_trees[CTI_NULL]
+
extern GTY(()) tree c_global_trees[CTI_MAX];
/* In a RECORD_TYPE, a sorted array of the fields of the type, not a
@@ -234,10 +222,6 @@ struct sorted_fields_type GTY(())
These may be shadowed, and may be referenced from nested functions. */
#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
-/* Flag strings given by __FUNCTION__ and __PRETTY_FUNCTION__ for a
- warning if they undergo concatenation. */
-#define C_ARTIFICIAL_STRING_P(NODE) TREE_LANG_FLAG_0 (NODE)
-
typedef enum c_language_kind
{
clk_c = 0, /* C90, C94 or C99 */
@@ -257,13 +241,9 @@ extern c_language_kind c_language;
/* Information about a statement tree. */
struct stmt_tree_s GTY(()) {
- /* The last statement added to the tree. */
- tree x_last_stmt;
- /* The type of the last expression statement. (This information is
- needed to implement the statement-expression extension.) */
- tree x_last_expr_type;
- /* The last filename we recorded. */
- const char *x_last_expr_filename;
+ /* The current statement list being collected. */
+ tree x_cur_stmt_list;
+
/* In C++, Nonzero if we should treat statements as full
expressions. In particular, this variable is no-zero if at the
end of a statement we should destroy any temporaries created
@@ -290,64 +270,42 @@ struct c_language_function GTY(()) {
/* While we are parsing the function, this contains information
about the statement-tree that we are building. */
struct stmt_tree_s x_stmt_tree;
- /* The stack of SCOPE_STMTs for the current function. */
- tree x_scope_stmt_stack;
};
-/* When building a statement-tree, this is the last statement added to
- the tree. */
-
-#define last_tree (current_stmt_tree ()->x_last_stmt)
-
-/* The type of the last expression-statement we have seen. */
-
-#define last_expr_type (current_stmt_tree ()->x_last_expr_type)
+/* When building a statement-tree, this is the current statement list
+ being collected. It's TREE_CHAIN is a back-pointer to the previous
+ statement list. */
-/* The name of the last file we have seen. */
-
-#define last_expr_filename (current_stmt_tree ()->x_last_expr_filename)
-
-/* LAST_TREE contains the last statement parsed. These are chained
- together through the TREE_CHAIN field, but often need to be
- re-organized since the parse is performed bottom-up. This macro
- makes LAST_TREE the indicated SUBSTMT of STMT. */
-
-#define RECHAIN_STMTS(stmt, substmt) \
- do { \
- substmt = TREE_CHAIN (stmt); \
- TREE_CHAIN (stmt) = NULL_TREE; \
- last_tree = stmt; \
- } while (0)
+#define cur_stmt_list (current_stmt_tree ()->x_cur_stmt_list)
/* Language-specific hooks. */
-extern void (*lang_expand_stmt) (tree);
-extern void (*lang_expand_decl_stmt) (tree);
-extern void (*lang_expand_function_end) (void);
-
/* Callback that determines if it's ok for a function to have no
noreturn attribute. */
extern int (*lang_missing_noreturn_ok_p) (tree);
-extern int yyparse (void);
+/* If non-NULL, this function is called after a precompile header file
+ is loaded. */
+extern void (*lang_post_pch_load) (void);
+
+extern void push_file_scope (void);
+extern void pop_file_scope (void);
extern stmt_tree current_stmt_tree (void);
-extern tree *current_scope_stmt_stack (void);
-extern void begin_stmt_tree (tree *);
+extern tree push_stmt_list (void);
+extern tree pop_stmt_list (tree);
extern tree add_stmt (tree);
-extern void add_decl_stmt (tree);
-extern tree add_scope_stmt (int, int);
-extern void finish_stmt_tree (tree *);
+extern void push_cleanup (tree, tree, bool);
+extern tree pushdecl_top_level (tree);
+extern tree pushdecl (tree);
+extern tree build_modify_expr (tree, enum tree_code, tree);
+extern tree build_indirect_ref (tree, const char *);
-extern tree walk_stmt_tree (tree *, walk_tree_fn, void *);
-extern void prep_stmt (tree);
-extern void expand_stmt (tree);
-extern tree c_begin_if_stmt (void);
-extern tree c_begin_while_stmt (void);
-extern void c_finish_while_stmt_cond (tree, tree);
+extern int c_expand_decl (tree);
extern int field_decl_cmp (const void *, const void *);
-extern void resort_sorted_fields (void *, void *, gt_pointer_operator,
- void *);
+extern void resort_sorted_fields (void *, void *, gt_pointer_operator,
+ void *);
+extern bool has_c_linkage (tree decl);
/* Switches common to the C front ends. */
@@ -364,6 +322,9 @@ extern int flag_nil_receivers;
@try, etc.) in source code. */
extern int flag_objc_exceptions;
+/* Nonzero means that we generate NeXT setjmp based exceptions. */
+extern int flag_objc_sjlj_exceptions;
+
/* Nonzero means that code generation will be altered to support
"zero-link" execution. This currently affects ObjC only, but may
affect other languages in the future. */
@@ -392,6 +353,10 @@ extern char flag_dump_macros;
extern char flag_dump_includes;
+/* Nonzero means process PCH files while preprocessing. */
+
+extern bool flag_pch_preprocess;
+
/* The file name to which we should write a precompiled header, or
NULL if no header will be written in this compile. */
@@ -439,107 +404,20 @@ extern int flag_const_strings;
/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */
extern int flag_signed_bitfields;
-extern int explicit_flag_signed_bitfields;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-extern int warn_cast_qual;
-
-/* Warn about functions which might be candidates for format attributes. */
-
-extern int warn_missing_format_attribute;
-
-/* Nonzero means do not warn that K&R style main() is not a function prototype. */
-extern int flag_bsd_no_warn_kr_main;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
- of function pointers. */
-
-extern int warn_pointer_arith;
-
-/* Nonzero means warn for any global function def
- without separate previous prototype decl. */
-
-extern int warn_missing_prototypes;
-
-/* Warn if adding () is suggested. */
-
-extern int warn_parentheses;
-
-/* Warn if initializer is not completely bracketed. */
-
-extern int warn_missing_braces;
-
-/* Warn about comparison of signed and unsigned values.
- If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */
-
-extern int warn_sign_compare;
-
-/* Nonzero means warn about usage of long long when `-pedantic'. */
-
-extern int warn_long_long;
-
-/* Nonzero means warn about deprecated conversion from string constant to
- `char *'. */
-
-extern int warn_write_strings;
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
+/* Warn about #pragma directives that are not recognized. */
-extern int warn_redundant_decls;
-
-/* Warn about testing equality of floating point numbers. */
-
-extern int warn_float_equal;
-
-/* Warn about a subscript that has type char. */
-
-extern int warn_char_subscripts;
-
-/* Warn if a type conversion is done that might have confusing results. */
-
-extern int warn_conversion;
-
-/* Warn about #pragma directives that are not recognized. */
-
-extern int warn_unknown_pragmas; /* Tri state variable. */
+extern int warn_unknown_pragmas; /* Tri state variable. */
/* Warn about format/argument anomalies in calls to formatted I/O functions
(*printf, *scanf, strftime, strfmon, etc.). */
extern int warn_format;
-/* Warn about Y2K problems with strftime formats. */
-
-extern int warn_format_y2k;
-
-/* Warn about excess arguments to formats. */
-
-extern int warn_format_extra_args;
-
-/* Warn about zero-length formats. */
-
-extern int warn_format_zero_length;
-
-/* Warn about non-literal format arguments. */
-
-extern int warn_format_nonliteral;
-
-/* Warn about possible security problems with calls to format functions. */
-
-extern int warn_format_security;
-
/* C/ObjC language option variables. */
-/* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error. */
-
-extern int mesg_implicit_function_declaration;
-
/* Nonzero means allow type mismatches in conditional expressions;
just make their values `void'. */
@@ -553,76 +431,14 @@ extern int flag_isoc94;
extern int flag_isoc99;
-/* Nonzero means allow the BSD kernel printf enhancments. */
-
-extern int flag_bsd_format;
-
/* Nonzero means that we have builtin functions, and main is an int. */
extern int flag_hosted;
-/* Nonzero means warn when casting a function call to a type that does
- not match the return type (e.g. (float)sqrt() or (anything*)malloc()
- when there is no previous declaration of sqrt or malloc. */
-
-extern int warn_bad_function_cast;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-extern int warn_traditional;
-
-/* Nonzero means warn for a declaration found after a statement. */
-
-extern int warn_declaration_after_statement;
-
-/* Nonzero means warn for non-prototype function decls
- or non-prototyped defs without previous prototype. */
-
-extern int warn_strict_prototypes;
-
-/* Nonzero means warn for any global function def
- without separate previous decl. */
-
-extern int warn_missing_declarations;
-
-/* Nonzero means warn about extern declarations of objects not at
- file-scope level and about *all* declarations of functions (whether
- extern or static) not at file-scope level. Note that we exclude
- implicit function declarations. To get warnings about those, use
- -Wimplicit. */
-
-extern int warn_nested_externs;
-
/* Warn if main is suspicious. */
extern int warn_main;
-/* Nonzero means warn about possible violations of sequence point rules. */
-
-extern int warn_sequence_point;
-
-/* Nonzero means warn about uninitialized variable when it is initialized with itself.
- For example: int i = i;, GCC will not warn about this when warn_init_self is nonzero. */
-
-extern int warn_init_self;
-
-
-/* Nonzero means to warn about compile-time division by zero. */
-extern int warn_div_by_zero;
-
-/* Nonzero means warn about use of implicit int. */
-
-extern int warn_implicit_int;
-
-/* Warn about NULL being passed to argument slots marked as requiring
- non-NULL. */
-
-extern int warn_nonnull;
-
-/* Warn about old-style parameter declaration. */
-
-extern int warn_old_style_definition;
-
/* ObjC language option variables. */
@@ -632,10 +448,6 @@ extern int warn_old_style_definition;
extern int flag_gen_declaration;
-/* Generate code for GNU or NeXT runtime environment. */
-
-extern int flag_next_runtime;
-
/* Tells the compiler that this is a special run. Do not perform any
compiling, instead we are to test some platform dependent features
and output a C header file with appropriate definitions. */
@@ -646,25 +458,6 @@ extern int print_struct_values;
extern const char *constant_string_class_name;
-/* Warn if multiple methods are seen for the same selector, but with
- different argument types. Performs the check on the whole selector
- table at the end of compilation. */
-
-extern int warn_selector;
-
-/* Warn if a @selector() is found, and no method with that selector
- has been previously declared. The check is done on each
- @selector() as soon as it is found - so it warns about forward
- declarations. */
-
-extern int warn_undeclared_selector;
-
-/* Warn if methods required by a protocol are not implemented in the
- class adopting it. When turned off, methods inherited to that
- class are also considered implemented. */
-
-extern int warn_protocol;
-
/* C++ language option variables. */
@@ -755,6 +548,11 @@ extern int flag_working_directory;
extern int flag_use_cxa_atexit;
+/* Nonzero to use __cxa_get_exception_ptr in the C++ exception-handling
+ logic. */
+
+extern int flag_use_cxa_get_exception_ptr;
+
/* Nonzero means make the default pedwarns warnings instead of errors.
The value of this flag is ignored if -pedantic is specified. */
@@ -767,69 +565,20 @@ extern int flag_permissive;
extern int flag_enforce_eh_specs;
-/* Nonzero means warn about things that will change when compiling
- with an ABI-compliant compiler. */
-
-extern int warn_abi;
+/* Nonzero (the default) means to generate thread-safe code for
+ initializing local statics. */
-/* Nonzero means warn about invalid uses of offsetof. */
-
-extern int warn_invalid_offsetof;
+extern int flag_threadsafe_statics;
/* Nonzero means warn about implicit declarations. */
extern int warn_implicit;
-/* Nonzero means warn when all ctors or dtors are private, and the class
- has no friends. */
-
-extern int warn_ctor_dtor_privacy;
-
-/* Nonzero means warn in function declared in derived class has the
- same name as a virtual in the base class, but fails to match the
- type signature of any virtual function in the base class. */
-
-extern int warn_overloaded_virtual;
-
-/* Nonzero means warn when declaring a class that has a non virtual
- destructor, when it really ought to have a virtual one. */
-
-extern int warn_nonvdtor;
-
-/* Nonzero means warn when the compiler will reorder code. */
-
-extern int warn_reorder;
-
-/* Nonzero means warn when synthesis behavior differs from Cfront's. */
-
-extern int warn_synth;
-
-/* Nonzero means warn when we convert a pointer to member function
- into a pointer to (void or function). */
-
-extern int warn_pmf2ptr;
-
-/* Nonzero means warn about violation of some Effective C++ style rules. */
-
-extern int warn_ecpp;
-
-/* Nonzero means warn where overload resolution chooses a promotion from
- unsigned to signed over a conversion to an unsigned of the same size. */
-
-extern int warn_sign_promo;
-
-/* Nonzero means warn when an old-style cast is used. */
-
-extern int warn_old_style_cast;
-
-/* Nonzero means warn when non-templatized friend functions are
- declared within a template */
+/* Warn about using __null (as NULL in C++) as sentinel. For code compiled
+ with GCC this doesn't matter as __null is guaranteed to have the right
+ size. */
-extern int warn_nontemplate_friend;
-
-/* Nonzero means complain about deprecated features. */
-
-extern int warn_deprecated;
+extern int warn_strict_null_sentinel;
/* Maximum template instantiation depth. This limit is rather
arbitrary, but it exists to limit the time it takes to notice
@@ -858,10 +607,6 @@ extern int skip_evaluation;
#define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \
(!C_TYPE_FUNCTION_P (type))
-/* Record in each node resulting from a binary operator
- what operator was specified for it. */
-#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
-
/* Attribute table common to the C front ends. */
extern const struct attribute_spec c_common_attribute_table[];
extern const struct attribute_spec c_common_format_attribute_table[];
@@ -881,13 +626,13 @@ extern void finish_fname_decls (void);
extern const char *fname_as_string (int);
extern tree fname_decl (unsigned, tree);
-extern void check_function_arguments (tree, tree);
+extern void check_function_arguments (tree, tree, tree);
extern void check_function_arguments_recurse (void (*)
(void *, tree,
unsigned HOST_WIDE_INT),
void *, tree,
unsigned HOST_WIDE_INT);
-extern void check_function_format (int *, tree, tree);
+extern void check_function_format (tree, tree);
extern void set_Wformat (int);
extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
@@ -898,36 +643,26 @@ extern tree c_common_type_for_size (unsigned int, int);
extern tree c_common_unsigned_type (tree);
extern tree c_common_signed_type (tree);
extern tree c_common_signed_or_unsigned_type (int, tree);
+extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
extern tree c_common_truthvalue_conversion (tree);
extern void c_apply_type_quals_to_decl (int, tree);
-extern tree c_sizeof_or_alignof_type (tree, enum tree_code, int);
+extern tree c_sizeof_or_alignof_type (tree, bool, int);
extern tree c_alignof_expr (tree);
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error (enum tree_code);
-#define my_friendly_assert(EXP, N) (void) \
- (((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0)
-
-extern tree c_expand_expr_stmt (tree);
-extern void c_expand_start_cond (tree, int, tree);
-extern void c_finish_then (void);
-extern void c_expand_start_else (void);
-extern void c_finish_else (void);
-extern void c_expand_end_cond (void);
-/* Validate the expression after `case' and apply default promotions. */
-extern tree check_case_value (tree);
extern tree fix_string_type (tree);
struct varray_head_tag;
extern void constant_expression_warning (tree);
+extern void strict_aliasing_warning(tree, tree, tree);
+extern void empty_body_warning (tree, tree);
extern tree convert_and_check (tree, tree);
extern void overflow_warning (tree);
-extern void unsigned_conversion_warning (tree, tree);
+extern bool c_determine_visibility (tree);
+extern bool same_scalar_type_ignoring_signedness (tree, tree);
-/* Read the rest of the current #-directive line. */
-extern char *get_directive_line (void);
-#define GET_DIRECTIVE_LINE() get_directive_line ()
-#define c_sizeof(T) c_sizeof_or_alignof_type (T, SIZEOF_EXPR, 1)
-#define c_alignof(T) c_sizeof_or_alignof_type (T, ALIGNOF_EXPR, 1)
+#define c_sizeof(T) c_sizeof_or_alignof_type (T, true, 1)
+#define c_alignof(T) c_sizeof_or_alignof_type (T, false, 1)
/* Subroutine of build_binary_op, used for comparison operations.
See if the operands have both been converted from subword integer types
@@ -944,8 +679,12 @@ extern tree c_build_qualified_type (tree, int);
frontends. */
extern void c_common_nodes_and_builtins (void);
+extern void set_builtin_user_assembler_name (tree decl, const char *asmspec);
+
extern void disable_builtin_function (const char *);
+extern void set_compound_literal_name (tree decl);
+
extern tree build_va_arg (tree, tree);
extern unsigned int c_common_init_options (unsigned int, const char **);
@@ -959,190 +698,30 @@ extern bool c_promoting_integer_type_p (tree);
extern int self_promoting_args_p (tree);
extern tree strip_array_types (tree);
extern tree strip_pointer_operator (tree);
+extern HOST_WIDE_INT c_common_to_target_charset (HOST_WIDE_INT);
-/* This function resets the parsers' state in preparation for parsing
- a new file. */
-extern void c_reset_state (void);
/* This is the basic parsing function. */
extern void c_parse_file (void);
/* This is misnamed, it actually performs end-of-compilation processing. */
extern void finish_file (void);
+
/* These macros provide convenient access to the various _STMT nodes. */
-/* Nonzero if this statement should be considered a full-expression,
- i.e., if temporaries created during this statement should have
- their destructors run at the end of this statement. (In C, this
- will always be false, since there are no destructors.) */
-#define STMT_IS_FULL_EXPR_P(NODE) TREE_LANG_FLAG_1 ((NODE))
-
-/* IF_STMT accessors. These give access to the condition of the if
- statement, the then block of the if statement, and the else block
- of the if statement if it exists. */
-#define IF_COND(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 0)
-#define THEN_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 1)
-#define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2)
-
-/* WHILE_STMT accessors. These give access to the condition of the
- while statement and the body of the while statement, respectively. */
-#define WHILE_COND(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 0)
-#define WHILE_BODY(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 1)
-
-/* DO_STMT accessors. These give access to the condition of the do
- statement and the body of the do statement, respectively. */
-#define DO_COND(NODE) TREE_OPERAND (DO_STMT_CHECK (NODE), 0)
-#define DO_BODY(NODE) TREE_OPERAND (DO_STMT_CHECK (NODE), 1)
-
-/* RETURN_STMT accessors. These give the expression associated with a
- return statement, and whether it should be ignored when expanding
- (as opposed to inlining). */
-#define RETURN_STMT_EXPR(NODE) TREE_OPERAND (RETURN_STMT_CHECK (NODE), 0)
-
-/* EXPR_STMT accessor. This gives the expression associated with an
- expression statement. */
-#define EXPR_STMT_EXPR(NODE) TREE_OPERAND (EXPR_STMT_CHECK (NODE), 0)
-
-/* FOR_STMT accessors. These give access to the init statement,
- condition, update expression, and body of the for statement,
- respectively. */
-#define FOR_INIT_STMT(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 0)
-#define FOR_COND(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 1)
-#define FOR_EXPR(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 2)
-#define FOR_BODY(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 3)
-
-/* SWITCH_STMT accessors. These give access to the condition, body and
- original condition type (before any compiler conversions)
- of the switch statement, respectively. */
-#define SWITCH_COND(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0)
-#define SWITCH_BODY(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 1)
-#define SWITCH_TYPE(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 2)
-
-/* CASE_LABEL accessors. These give access to the high and low values
- of a case label, respectively. */
-#define CASE_LOW(NODE) TREE_OPERAND (CASE_LABEL_CHECK (NODE), 0)
-#define CASE_HIGH(NODE) TREE_OPERAND (CASE_LABEL_CHECK (NODE), 1)
-#define CASE_LABEL_DECL(NODE) TREE_OPERAND (CASE_LABEL_CHECK (NODE), 2)
-
-/* GOTO_STMT accessor. This gives access to the label associated with
- a goto statement. */
-#define GOTO_DESTINATION(NODE) TREE_OPERAND (GOTO_STMT_CHECK (NODE), 0)
-/* True for goto created artificially by the compiler. */
-#define GOTO_FAKE_P(NODE) (TREE_LANG_FLAG_0 (GOTO_STMT_CHECK (NODE)))
-
-/* COMPOUND_STMT accessor. This gives access to the TREE_LIST of
- statements associated with a compound statement. The result is the
- first statement in the list. Succeeding nodes can be accessed by
- calling TREE_CHAIN on a node in the list. */
-#define COMPOUND_BODY(NODE) TREE_OPERAND (COMPOUND_STMT_CHECK (NODE), 0)
-
-/* ASM_STMT accessors. ASM_STRING returns a STRING_CST for the
- instruction (e.g., "mov x, y"). ASM_OUTPUTS, ASM_INPUTS, and
- ASM_CLOBBERS represent the outputs, inputs, and clobbers for the
- statement. */
-#define ASM_CV_QUAL(NODE) TREE_OPERAND (ASM_STMT_CHECK (NODE), 0)
-#define ASM_STRING(NODE) TREE_OPERAND (ASM_STMT_CHECK (NODE), 1)
-#define ASM_OUTPUTS(NODE) TREE_OPERAND (ASM_STMT_CHECK (NODE), 2)
-#define ASM_INPUTS(NODE) TREE_OPERAND (ASM_STMT_CHECK (NODE), 3)
-#define ASM_CLOBBERS(NODE) TREE_OPERAND (ASM_STMT_CHECK (NODE), 4)
-
-/* DECL_STMT accessor. This gives access to the DECL associated with
- the given declaration statement. */
-#define DECL_STMT_DECL(NODE) TREE_OPERAND (DECL_STMT_CHECK (NODE), 0)
-
-/* STMT_EXPR accessor. */
-#define STMT_EXPR_STMT(NODE) TREE_OPERAND (STMT_EXPR_CHECK (NODE), 0)
-
-/* Nonzero if this statement-expression does not have an associated scope. */
-#define STMT_EXPR_NO_SCOPE(NODE) \
- TREE_LANG_FLAG_0 (STMT_EXPR_CHECK (NODE))
-
-/* Nonzero if this statement-expression should cause warning if its result
- is not used. */
-#define STMT_EXPR_WARN_UNUSED_RESULT(NODE) \
- TREE_LANG_FLAG_3 (STMT_EXPR_CHECK (NODE))
-
-/* LABEL_STMT accessor. This gives access to the label associated with
- the given label statement. */
-#define LABEL_STMT_LABEL(NODE) TREE_OPERAND (LABEL_STMT_CHECK (NODE), 0)
+/* Nonzero if a given STATEMENT_LIST represents the outermost binding
+ if a statement expression. */
+#define STATEMENT_LIST_STMT_EXPR(NODE) \
+ TREE_LANG_FLAG_1 (STATEMENT_LIST_CHECK (NODE))
+
+/* Nonzero if a label has been added to the statement list. */
+#define STATEMENT_LIST_HAS_LABEL(NODE) \
+ TREE_LANG_FLAG_3 (STATEMENT_LIST_CHECK (NODE))
/* COMPOUND_LITERAL_EXPR accessors. */
#define COMPOUND_LITERAL_EXPR_DECL_STMT(NODE) \
TREE_OPERAND (COMPOUND_LITERAL_EXPR_CHECK (NODE), 0)
#define COMPOUND_LITERAL_EXPR_DECL(NODE) \
- DECL_STMT_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE))
-
-/* Nonzero if this SCOPE_STMT is for the beginning of a scope. */
-#define SCOPE_BEGIN_P(NODE) \
- (TREE_LANG_FLAG_0 (SCOPE_STMT_CHECK (NODE)))
-
-/* Nonzero if this SCOPE_STMT is for the end of a scope. */
-#define SCOPE_END_P(NODE) \
- (!SCOPE_BEGIN_P (SCOPE_STMT_CHECK (NODE)))
-
-/* The BLOCK containing the declarations contained in this scope. */
-#define SCOPE_STMT_BLOCK(NODE) \
- (TREE_OPERAND (SCOPE_STMT_CHECK (NODE), 0))
-
-/* Nonzero for a SCOPE_STMT if there were no variables in this scope. */
-#define SCOPE_NULLIFIED_P(NODE) \
- (SCOPE_STMT_BLOCK ((NODE)) == NULL_TREE)
-
-/* Nonzero for a SCOPE_STMT which represents a lexical scope, but
- which should be treated as non-existent from the point of view of
- running cleanup actions. */
-#define SCOPE_NO_CLEANUPS_P(NODE) \
- (TREE_LANG_FLAG_3 (SCOPE_STMT_CHECK (NODE)))
-
-/* Nonzero for a SCOPE_STMT if this statement is for a partial scope.
- For example, in:
-
- S s;
- l:
- S s2;
- goto l;
-
- there is (implicitly) a new scope after `l', even though there are
- no curly braces. In particular, when we hit the goto, we must
- destroy s2 and then re-construct it. For the implicit scope,
- SCOPE_PARTIAL_P will be set. */
-#define SCOPE_PARTIAL_P(NODE) \
- (TREE_LANG_FLAG_4 (SCOPE_STMT_CHECK (NODE)))
-
-/* Nonzero for an ASM_STMT if the assembly statement is volatile. */
-#define ASM_VOLATILE_P(NODE) \
- (ASM_CV_QUAL (ASM_STMT_CHECK (NODE)) != NULL_TREE)
-
-/* The VAR_DECL to clean up in a CLEANUP_STMT. */
-#define CLEANUP_DECL(NODE) \
- TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 0)
-/* The cleanup to run in a CLEANUP_STMT. */
-#define CLEANUP_EXPR(NODE) \
- TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 1)
-
-/* The filename we are changing to as of this FILE_STMT. */
-#define FILE_STMT_FILENAME_NODE(NODE) \
- (TREE_OPERAND (FILE_STMT_CHECK (NODE), 0))
-#define FILE_STMT_FILENAME(NODE) \
- (IDENTIFIER_POINTER (FILE_STMT_FILENAME_NODE (NODE)))
-
-/* The line-number at which a statement began. But if
- STMT_LINENO_FOR_FN_P does holds, then this macro gives the
- line number for the end of the current function instead. */
-#define STMT_LINENO(NODE) \
- (TREE_COMPLEXITY ((NODE)))
-
-/* If nonzero, the STMT_LINENO for NODE is the line at which the
- function ended. */
-#define STMT_LINENO_FOR_FN_P(NODE) \
- (TREE_LANG_FLAG_2 ((NODE)))
-
-/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
- initialization variables. */
-#define NEW_FOR_SCOPE_P(NODE) (TREE_LANG_FLAG_0 (NODE))
-
-/* Nonzero if we want to create an ASM_INPUT instead of an
- ASM_OPERAND with no operands. */
-#define ASM_INPUT_P(NODE) (TREE_LANG_FLAG_0 (NODE))
+ DECL_EXPR_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE))
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
@@ -1154,47 +733,6 @@ enum c_tree_code {
#undef DEFTREECODE
-#define c_common_stmt_codes \
- CLEANUP_STMT, EXPR_STMT, COMPOUND_STMT, \
- DECL_STMT, IF_STMT, FOR_STMT, \
- WHILE_STMT, DO_STMT, RETURN_STMT, \
- BREAK_STMT, CONTINUE_STMT, SCOPE_STMT, \
- SWITCH_STMT, GOTO_STMT, LABEL_STMT, \
- ASM_STMT, FILE_STMT, CASE_LABEL
-
-/* TRUE if a code represents a statement. The front end init
- langhook should take care of initialization of this array. */
-extern bool statement_code_p[MAX_TREE_CODES];
-
-#define STATEMENT_CODE_P(CODE) statement_code_p[(int) (CODE)]
-
-#define INIT_STATEMENT_CODES(STMT_CODES) \
- do { \
- unsigned int i; \
- memset (&statement_code_p, 0, sizeof (statement_code_p)); \
- for (i = 0; i < ARRAY_SIZE (STMT_CODES); i++) \
- statement_code_p[STMT_CODES[i]] = true; \
- } while (0)
-
-extern void genrtl_do_pushlevel (void);
-extern void genrtl_goto_stmt (tree);
-extern void genrtl_expr_stmt (tree);
-extern void genrtl_expr_stmt_value (tree, int, int);
-extern void genrtl_decl_stmt (tree);
-extern void genrtl_if_stmt (tree);
-extern void genrtl_while_stmt (tree);
-extern void genrtl_do_stmt (tree);
-extern void genrtl_return_stmt (tree);
-extern void genrtl_for_stmt (tree);
-extern void genrtl_break_stmt (void);
-extern void genrtl_continue_stmt (void);
-extern void genrtl_scope_stmt (tree);
-extern void genrtl_switch_stmt (tree);
-extern void genrtl_case_label (tree);
-extern void genrtl_compound_stmt (tree);
-extern void genrtl_asm_stmt (tree, tree, tree, tree, tree, int);
-extern void genrtl_cleanup_stmt (tree);
-extern int stmts_are_full_exprs_p (void);
extern int anon_aggr_type_p (tree);
/* For a VAR_DECL that is an anonymous union, these are the various
@@ -1209,35 +747,21 @@ extern int anon_aggr_type_p (tree);
#define CLEAR_DECL_C_BIT_FIELD(NODE) \
(DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 0)
-/* In a VAR_DECL, nonzero if the decl is a register variable with
- an explicit asm specification. */
-#define DECL_C_HARD_REGISTER(DECL) DECL_LANG_FLAG_4 (VAR_DECL_CHECK (DECL))
-
extern void emit_local_var (tree);
-extern void make_rtl_for_local_static (tree);
-extern tree expand_cond (tree);
-extern tree c_expand_return (tree);
extern tree do_case (tree, tree);
extern tree build_stmt (enum tree_code, ...);
extern tree build_case_label (tree, tree, tree);
-extern tree build_continue_stmt (void);
-extern tree build_break_stmt (void);
-extern tree build_return_stmt (tree);
-
-#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
-
-/* Used by the C++ frontend to mark the block around the member
- initializers and cleanups. */
-#define COMPOUND_STMT_BODY_BLOCK(NODE) TREE_LANG_FLAG_3 (NODE)
-
-extern void c_expand_asm_operands (tree, tree, tree, tree, int, location_t);
/* These functions must be defined by each front-end which implements
a variant of the C language. They are used in c-common.c. */
extern tree build_unary_op (enum tree_code, tree, int);
extern tree build_binary_op (enum tree_code, tree, tree, int);
-extern int lvalue_p (tree);
+extern tree perform_integral_promotions (tree);
+
+/* These functions must be defined by each front-end which implements
+ a variant of the C language. They are used by port files. */
+
extern tree default_conversion (tree);
/* Given two integer or real types, return the type for their sum.
@@ -1245,38 +769,33 @@ extern tree default_conversion (tree);
extern tree common_type (tree, tree);
-extern tree expand_tree_builtin (tree, tree, tree);
-
extern tree decl_constant_value (tree);
/* Handle increment and decrement of boolean types. */
extern tree boolean_increment (enum tree_code, tree);
-/* Hook currently used only by the C++ front end to reset internal state
- after entering or leaving a header file. */
-extern void extract_interface_info (void);
-
extern int case_compare (splay_tree_key, splay_tree_key);
-extern tree c_add_case_label (splay_tree, tree, tree, tree);
+extern tree c_add_case_label (splay_tree, tree, tree, tree, tree);
+
+extern void c_do_switch_warnings (splay_tree, location_t, tree, tree);
extern tree build_function_call (tree, tree);
+extern tree resolve_overloaded_builtin (tree, tree);
+
extern tree finish_label_address_expr (tree);
/* Same function prototype, but the C and C++ front ends have
different implementations. Used in c-common.c. */
extern tree lookup_label (tree);
+extern tree lookup_name (tree);
extern int vector_types_convertible_p (tree t1, tree t2);
extern rtx c_expand_expr (tree, rtx, enum machine_mode, int, rtx *);
-extern int c_safe_from_p (rtx, tree);
-
-extern int c_staticp (tree);
-
-extern int c_common_unsafe_for_reeval (tree);
+extern tree c_staticp (tree);
extern void init_c_lex (void);
@@ -1284,14 +803,21 @@ extern void c_cpp_builtins (cpp_reader *);
/* Positive if an implicit `extern "C"' scope has just been entered;
negative if such a scope has just been exited. */
-extern int pending_lang_change;
+extern GTY(()) int pending_lang_change;
/* Information recorded about each file examined during compilation. */
struct c_fileinfo
{
int time; /* Time spent in the file. */
- short interface_only; /* Flags - used only by C++ */
+
+ /* Flags used only by C++.
+ INTERFACE_ONLY nonzero means that we are in an "interface" section
+ of the compiler. INTERFACE_UNKNOWN nonzero means we cannot trust
+ the value of INTERFACE_ONLY. If INTERFACE_UNKNOWN is zero and
+ INTERFACE_ONLY is zero, it means that we are responsible for
+ exporting definitions that others might need. */
+ short interface_only;
short interface_unknown;
};
@@ -1300,30 +826,114 @@ extern void dump_time_statistics (void);
extern bool c_dump_tree (void *, tree);
+extern void c_warn_unused_result (tree *);
+
+extern void verify_sequence_points (tree);
+
+extern tree fold_offsetof (tree, tree);
+
+/* Places where an lvalue, or modifiable lvalue, may be required.
+ Used to select diagnostic messages in lvalue_error and
+ readonly_error. */
+enum lvalue_use {
+ lv_assign,
+ lv_increment,
+ lv_decrement,
+ lv_addressof,
+ lv_asm
+};
+
+extern void lvalue_error (enum lvalue_use);
+
+extern int complete_array_type (tree *, tree, bool);
+
+extern tree builtin_type_for_size (int, bool);
+
+extern void warn_array_subscript_with_type_char (tree);
+
+/* In c-gimplify.c */
+extern void c_genericize (tree);
+extern int c_gimplify_expr (tree *, tree *, tree *);
+extern tree c_build_bind_expr (tree, tree);
+
+/* In c-pch.c */
extern void pch_init (void);
extern int c_common_valid_pch (cpp_reader *pfile, const char *name, int fd);
extern void c_common_read_pch (cpp_reader *pfile, const char *name, int fd,
const char *orig);
extern void c_common_write_pch (void);
extern void c_common_no_more_pch (void);
+extern void c_common_pch_pragma (cpp_reader *pfile, const char *);
+extern void c_common_print_pch_checksum (FILE *f);
+
+/* In *-checksum.c */
+extern const unsigned char executable_checksum[16];
+
extern void builtin_define_with_value (const char *, const char *, int);
extern void c_stddef_cpp_builtins (void);
extern void fe_file_change (const struct line_map *);
-extern int c_estimate_num_insns (tree decl);
-extern bool c_decl_uninit (tree t);
extern void c_parse_error (const char *, enum cpp_ttype, tree);
-/* The following have been moved here from c-tree.h, since they're needed
- in the ObjC++ world, too. What is more, stub-objc.c could use a few
- prototypes. */
-extern tree lookup_interface (tree);
-extern tree is_class_name (tree);
+/* Objective-C / Objective-C++ entry points. */
+
+/* The following ObjC/ObjC++ functions are called by the C and/or C++
+ front-ends; they all must have corresponding stubs in stub-objc.c. */
+extern tree objc_is_class_name (tree);
extern tree objc_is_object_ptr (tree);
extern void objc_check_decl (tree);
-extern int objc_comptypes (tree, tree, int);
+extern int objc_is_reserved_word (tree);
+extern bool objc_compare_types (tree, tree, int, tree);
+extern void objc_volatilize_decl (tree);
+extern bool objc_type_quals_match (tree, tree);
+extern tree objc_rewrite_function_call (tree, tree);
extern tree objc_message_selector (void);
-extern tree lookup_objc_ivar (tree);
-extern void *get_current_scope (void);
+extern tree objc_lookup_ivar (tree, tree);
+extern void objc_clear_super_receiver (void);
+extern int objc_is_public (tree, tree);
+extern tree objc_is_id (tree);
+extern void objc_declare_alias (tree, tree);
+extern void objc_declare_class (tree);
+extern void objc_declare_protocols (tree);
+extern tree objc_build_message_expr (tree);
+extern tree objc_finish_message_expr (tree, tree, tree);
+extern tree objc_build_selector_expr (tree);
+extern tree objc_build_protocol_expr (tree);
+extern tree objc_build_encode_expr (tree);
+extern tree objc_build_string_object (tree);
+extern tree objc_get_protocol_qualified_type (tree, tree);
+extern tree objc_get_class_reference (tree);
+extern tree objc_get_class_ivars (tree);
+extern void objc_start_class_interface (tree, tree, tree);
+extern void objc_start_category_interface (tree, tree, tree);
+extern void objc_start_protocol (tree, tree);
+extern void objc_continue_interface (void);
+extern void objc_finish_interface (void);
+extern void objc_start_class_implementation (tree, tree);
+extern void objc_start_category_implementation (tree, tree);
+extern void objc_continue_implementation (void);
+extern void objc_finish_implementation (void);
+extern void objc_set_visibility (int);
+extern void objc_set_method_type (enum tree_code);
+extern tree objc_build_method_signature (tree, tree, tree, bool);
+extern void objc_add_method_declaration (tree);
+extern void objc_start_method_definition (tree);
+extern void objc_finish_method_definition (tree);
+extern void objc_add_instance_variable (tree);
+extern tree objc_build_keyword_decl (tree, tree, tree);
+extern tree objc_build_throw_stmt (tree);
+extern void objc_begin_try_stmt (location_t, tree);
+extern tree objc_finish_try_stmt (void);
+extern void objc_begin_catch_clause (tree);
+extern void objc_finish_catch_clause (void);
+extern void objc_build_finally_clause (location_t, tree);
+extern tree objc_build_synchronized (location_t, tree, tree);
+extern int objc_static_init_needed_p (void);
+extern tree objc_generate_static_init_call (tree);
+extern tree objc_generate_write_barrier (tree, enum tree_code, tree);
+
+/* The following are provided by the C and C++ front-ends, and called by
+ ObjC/ObjC++. */
+extern void *objc_get_current_scope (void);
extern void objc_mark_locals_volatile (void *);
/* In c-ppoutput.c */
@@ -1331,5 +941,30 @@ extern void init_pp_output (FILE *);
extern void preprocess_file (cpp_reader *);
extern void pp_file_change (const struct line_map *);
extern void pp_dir_change (cpp_reader *, const char *);
+extern bool check_missing_format_attribute (tree, tree);
+
+/* In c-omp.c */
+extern tree c_finish_omp_master (tree);
+extern tree c_finish_omp_critical (tree, tree);
+extern tree c_finish_omp_ordered (tree);
+extern void c_finish_omp_barrier (void);
+extern tree c_finish_omp_atomic (enum tree_code, tree, tree);
+extern void c_finish_omp_flush (void);
+extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree);
+extern void c_split_parallel_clauses (tree, tree *, tree *);
+extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
+
+/* Not in c-omp.c; provided by the front end. */
+extern bool c_omp_sharing_predetermined (tree);
+extern tree c_omp_remap_decl (tree, bool);
+
+/* In order for the format checking to accept the C frontend
+ diagnostic framework extensions, you must include this file before
+ toplev.h, not after. The C front end formats are a subset of those
+ for C++, so they are the appropriate set to use in common code;
+ cp-tree.h overrides this for C++. */
+#ifndef GCC_DIAG_STYLE
+#define GCC_DIAG_STYLE __gcc_cdiag__
+#endif
#endif /* ! GCC_C_COMMON_H */
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c
index af6d668..5c46615 100644
--- a/contrib/gcc/c-decl.c
+++ b/contrib/gcc/c-decl.c
@@ -1,6 +1,6 @@
/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* $FreeBSD$ */
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "input.h"
#include "tm.h"
#include "intl.h"
#include "tree.h"
@@ -51,11 +52,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
+#include "langhooks.h"
+#include "tree-mudflap.h"
+#include "tree-gimple.h"
+#include "diagnostic.h"
+#include "tree-dump.h"
#include "cgraph.h"
#include "hashtab.h"
#include "libfuncs.h"
#include "except.h"
#include "langhooks-def.h"
+#include "pointer-set.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -68,11 +75,14 @@ enum decl_context
/* Nonzero if we have seen an invalid cross reference
to a struct, union, or enum, but not yet printed the message. */
-
tree pending_invalid_xref;
+
/* File and line to appear in the eventual error message. */
location_t pending_invalid_xref_location;
+/* True means we've initialized exception handling. */
+bool c_eh_initialized_p;
+
/* While defining an enum type, this is 1 plus the last enumerator
constant value. Note that will do not have to save this or `enum_overflow'
around nested function definition since such a definition could only
@@ -85,64 +95,46 @@ static tree enum_next_value;
static int enum_overflow;
-/* Parsing a function declarator leaves a list of parameter names
- or a chain of parameter decls here. */
-
-static tree last_function_parms;
-
-/* ... and a chain of structure and enum types declared in the
- parmlist here. */
-
-static tree last_function_parm_tags;
+/* The file and line that the prototype came from if this is an
+ old-style definition; used for diagnostics in
+ store_parm_decls_oldstyle. */
-/* ... and a chain of all non-parameter declarations (such as
- CONST_DECLs from enumerations) here. */
-
-static tree last_function_parm_others;
-
-/* After parsing the declarator that starts a function definition,
- `start_function' puts the list of parameter names or chain of decls here
- for `store_parm_decls' to find. */
+static location_t current_function_prototype_locus;
-static tree current_function_parms;
+/* Whether this prototype was built-in. */
-/* Similar, for last_function_parm_tags. */
+static bool current_function_prototype_built_in;
-static tree current_function_parm_tags;
+/* The argument type information of this prototype. */
-/* And for last_function_parm_others. */
+static tree current_function_prototype_arg_types;
-static tree current_function_parm_others;
+/* The argument information structure for the function currently being
+ defined. */
-/* Similar, for the file and line that the prototype came from if this is
- an old-style definition. */
+static struct c_arg_info *current_function_arg_info;
-static location_t current_function_prototype_locus;
+/* The obstack on which parser and related data structures, which are
+ not live beyond their top-level declaration or definition, are
+ allocated. */
+struct obstack parser_obstack;
/* The current statement tree. */
static GTY(()) struct stmt_tree_s c_stmt_tree;
-/* The current scope statement stack. */
-
-static GTY(()) tree c_scope_stmt_stack;
-
/* State saving variables. */
-int c_in_iteration_stmt;
-int c_in_case_stmt;
+tree c_break_label;
+tree c_cont_label;
-/* A list of external DECLs that appeared at block scope when there was
- some other global meaning for that identifier. */
-static GTY(()) tree truly_local_externals;
+/* Linked list of TRANSLATION_UNIT_DECLS for the translation units
+ included in this invocation. Note that the current translation
+ unit is not included in this list. */
-/* All the builtins; this is a subset of the entries of global_scope. */
+static GTY(()) tree all_translation_units;
-static GTY(()) tree first_builtin_decl;
-static GTY(()) tree last_builtin_decl;
-
-/* A DECL for the current file-scope context. */
-
-static GTY(()) tree current_file_decl;
+/* A list of decls to be made automatically visible in each file scope. */
+static GTY(()) tree visible_builtins;
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -167,10 +159,115 @@ static int warn_about_return_type;
/* Nonzero when starting a function declared `extern inline'. */
static int current_extern_inline;
+
+/* Nonzero when the current toplevel function contains a declaration
+ of a nested function which is never defined. */
+
+static bool undef_nested_function;
+
+/* True means global_bindings_p should return false even if the scope stack
+ says we are in file scope. */
+bool c_override_global_bindings_to_false;
+
-/* Each c_scope structure describes the complete contents of one scope.
- Three scopes are distinguished specially: the innermost or current
- scope, the innermost function scope, and the outermost or file scope.
+/* Each c_binding structure describes one binding of an identifier to
+ a decl. All the decls in a scope - irrespective of namespace - are
+ chained together by the ->prev field, which (as the name implies)
+ runs in reverse order. All the decls in a given namespace bound to
+ a given identifier are chained by the ->shadowed field, which runs
+ from inner to outer scopes.
+
+ The ->decl field usually points to a DECL node, but there are two
+ exceptions. In the namespace of type tags, the bound entity is a
+ RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node. If an undeclared
+ identifier is encountered, it is bound to error_mark_node to
+ suppress further errors about that identifier in the current
+ function.
+
+ The ->type field stores the type of the declaration in this scope;
+ if NULL, the type is the type of the ->decl field. This is only of
+ relevance for objects with external or internal linkage which may
+ be redeclared in inner scopes, forming composite types that only
+ persist for the duration of those scopes. In the external scope,
+ this stores the composite of all the types declared for this
+ object, visible or not. The ->inner_comp field (used only at file
+ scope) stores whether an incomplete array type at file scope was
+ completed at an inner scope to an array size other than 1.
+
+ The depth field is copied from the scope structure that holds this
+ decl. It is used to preserve the proper ordering of the ->shadowed
+ field (see bind()) and also for a handful of special-case checks.
+ Finally, the invisible bit is true for a decl which should be
+ ignored for purposes of normal name lookup, and the nested bit is
+ true for a decl that's been bound a second time in an inner scope;
+ in all such cases, the binding in the outer scope will have its
+ invisible bit true. */
+
+struct c_binding GTY((chain_next ("%h.prev")))
+{
+ tree decl; /* the decl bound */
+ tree type; /* the type in this scope */
+ tree id; /* the identifier it's bound to */
+ struct c_binding *prev; /* the previous decl in this scope */
+ struct c_binding *shadowed; /* the innermost decl shadowed by this one */
+ unsigned int depth : 28; /* depth of this scope */
+ BOOL_BITFIELD invisible : 1; /* normal lookup should ignore this binding */
+ BOOL_BITFIELD nested : 1; /* do not set DECL_CONTEXT when popping */
+ BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
+ /* one free bit */
+};
+#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
+#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
+#define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/)
+#define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
+
+#define I_SYMBOL_BINDING(node) \
+ (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding)
+#define I_SYMBOL_DECL(node) \
+ (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
+
+#define I_TAG_BINDING(node) \
+ (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding)
+#define I_TAG_DECL(node) \
+ (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
+
+#define I_LABEL_BINDING(node) \
+ (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding)
+#define I_LABEL_DECL(node) \
+ (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
+
+/* Each C symbol points to three linked lists of c_binding structures.
+ These describe the values of the identifier in the three different
+ namespaces defined by the language. */
+
+struct lang_identifier GTY(())
+{
+ struct c_common_identifier common_id;
+ struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
+ struct c_binding *tag_binding; /* struct/union/enum tags */
+ struct c_binding *label_binding; /* labels */
+};
+
+/* Validate c-lang.c's assumptions. */
+extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
+[(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
+
+/* The resulting tree type. */
+
+union lang_tree_node
+ GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+ chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *) TREE_CHAIN (&%h.generic)")))
+{
+ union tree_node GTY ((tag ("0"),
+ desc ("tree_node_structure (&%h)")))
+ generic;
+ struct lang_identifier GTY ((tag ("1"))) identifier;
+};
+
+/* Each c_scope structure describes the complete contents of one
+ scope. Four scopes are distinguished specially: the innermost or
+ current scope, the innermost function scope, the file scope (always
+ the second to outermost) and the outermost or external scope.
Most declarations are recorded in the current scope.
@@ -180,20 +277,39 @@ static int current_extern_inline;
hence the 'innermost' qualifier.) Explicitly declared labels
(using the __label__ extension) appear in the current scope.
- Being in the global scope (current_scope == global_scope) causes
+ Being in the file scope (current_scope == file_scope) causes
special behavior in several places below. Also, under some
conditions the Objective-C front end records declarations in the
- global scope even though that isn't the current scope.
+ file scope even though that isn't the current scope.
+
+ All declarations with external linkage are recorded in the external
+ scope, even if they aren't visible there; this models the fact that
+ such declarations are visible to the entire program, and (with a
+ bit of cleverness, see pushdecl) allows diagnosis of some violations
+ of C99 6.2.2p7 and 6.2.7p2:
+
+ If, within the same translation unit, the same identifier appears
+ with both internal and external linkage, the behavior is
+ undefined.
- The order of the names, parms, and blocks lists matters, and they
- are frequently appended to. To avoid having to walk all the way to
- the end of the list on each insertion, or reverse the lists later,
- we maintain a pointer to the last list entry for each of the lists.
+ All declarations that refer to the same object or function shall
+ have compatible type; otherwise, the behavior is undefined.
- The order of the tags, shadowed, and shadowed_tags
- lists does not matter, so we just prepend to these lists. */
+ Initially only the built-in declarations, which describe compiler
+ intrinsic functions plus a subset of the standard library, are in
+ this scope.
-struct c_scope GTY(())
+ The order of the blocks list matters, and it is frequently appended
+ to. To avoid having to walk all the way to the end of the list on
+ each insertion, or reverse the list later, we maintain a pointer to
+ the last list entry. (FIXME: It should be feasible to use a reversed
+ list here.)
+
+ The bindings list is strictly in reverse order of declarations;
+ pop_scope relies on this. */
+
+
+struct c_scope GTY((chain_next ("%h.outer")))
{
/* The scope containing this one. */
struct c_scope *outer;
@@ -201,39 +317,26 @@ struct c_scope GTY(())
/* The next outermost function scope. */
struct c_scope *outer_function;
- /* All variables, constants, functions, labels, and typedef names. */
- tree names;
- tree names_last;
-
- /* All parameter declarations. Used only in the outermost scope of
- a function. */
- tree parms;
- tree parms_last;
-
- /* All structure, union, and enum type tags. */
- tree tags;
-
- /* For each scope, a list of shadowed outer-scope definitions
- to be restored when this scope is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* For each scope, a list of shadowed outer-scope tag definitions
- to be restored when this scope is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._TYPE node). */
- tree shadowed_tags;
+ /* All bindings in this scope. */
+ struct c_binding *bindings;
/* For each scope (except the global one), a chain of BLOCK nodes
for all the scopes that were entered and exited one level down. */
tree blocks;
tree blocks_last;
+ /* The depth of this scope. Used to keep the ->shadowed chain of
+ bindings sorted innermost to outermost. */
+ unsigned int depth : 28;
+
/* True if we are currently filling this scope with parameter
declarations. */
BOOL_BITFIELD parm_flag : 1;
+ /* True if we saw [*] in this scope. Used to give an error messages
+ if these appears in a function definition. */
+ BOOL_BITFIELD had_vla_unspec : 1;
+
/* True if we already complained about forward parameter decls
in this scope. This prevents double warnings on
foo (int a; int b; ...) */
@@ -253,20 +356,28 @@ struct c_scope GTY(())
static GTY(()) struct c_scope *current_scope;
-/* A chain of c_scope structures awaiting reuse. */
-
-static GTY((deletable (""))) struct c_scope *scope_freelist;
-
/* The innermost function scope. Ordinary (not explicitly declared)
labels, bindings to error_mark_node, and the lazily-created
bindings of __func__ and its friends get this scope. */
static GTY(()) struct c_scope *current_function_scope;
-/* The outermost scope, corresponding to the C "file scope". This is
- created when the compiler is started and exists through the entire run. */
+/* The C file scope. This is reset for each input translation unit. */
+
+static GTY(()) struct c_scope *file_scope;
+
+/* The outermost scope. This is used for all declarations with
+ external linkage, and only these, hence the name. */
+
+static GTY(()) struct c_scope *external_scope;
+
+/* A chain of c_scope structures awaiting reuse. */
-static GTY(()) struct c_scope *global_scope;
+static GTY((deletable)) struct c_scope *scope_freelist;
+
+/* A chain of c_binding structures awaiting reuse. */
+
+static GTY((deletable)) struct c_binding *binding_freelist;
/* Append VAR to LIST in scope SCOPE. */
#define SCOPE_LIST_APPEND(scope, list, decl) do { \
@@ -294,7 +405,7 @@ static GTY(()) struct c_scope *global_scope;
static bool keep_next_level_flag;
-/* True means the next call to pushlevel will be the outermost scope
+/* True means the next call to push_scope will be the outermost scope
of a function body, so do not push a new scope, merely cease
expecting parameter decls. */
@@ -302,32 +413,42 @@ static bool next_is_function_body;
/* Functions called automatically at the beginning and end of execution. */
-tree static_ctors, static_dtors;
+static GTY(()) tree static_ctors;
+static GTY(()) tree static_dtors;
/* Forward declarations. */
-
-static struct c_scope *make_scope (void);
-static void pop_scope (void);
-static tree make_label (tree, location_t);
-static void bind_label (tree, tree, struct c_scope *);
-static void implicit_decl_warning (tree);
-static tree lookup_tag (enum tree_code, tree, int);
-static tree lookup_name_current_level (tree);
-static tree grokdeclarator (tree, tree, enum decl_context, int, tree *);
-static tree grokparms (tree, int);
-static void layout_array_type (tree);
-static void store_parm_decls_newstyle (void);
-static void store_parm_decls_oldstyle (void);
+static tree lookup_name_in_scope (tree, struct c_scope *);
static tree c_make_fname_decl (tree, int);
-static void c_expand_body_1 (tree, int);
-static tree any_external_decl (tree);
-static void record_external_decl (tree);
-static void warn_if_shadowing (tree, tree);
-static void check_bitfield_type_and_width (tree *, tree *, const char *);
-static void clone_underlying_type (tree);
-static bool flexible_array_type_p (tree);
-static hashval_t link_hash_hash (const void *);
-static int link_hash_eq (const void *, const void *);
+static tree grokdeclarator (const struct c_declarator *,
+ struct c_declspecs *,
+ enum decl_context, bool, tree *);
+static tree grokparms (struct c_arg_info *, bool);
+static void layout_array_type (tree);
+
+/* T is a statement. Add it to the statement-tree. This is the
+ C/ObjC version--C++ has a slightly different version of this
+ function. */
+
+tree
+add_stmt (tree t)
+{
+ enum tree_code code = TREE_CODE (t);
+
+ if (EXPR_P (t) && code != LABEL_EXPR)
+ {
+ if (!EXPR_HAS_LOCATION (t))
+ SET_EXPR_LOCATION (t, input_location);
+ }
+
+ if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
+ STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1;
+
+ /* Add T to the statement-tree. Non-side-effect statements need to be
+ recorded during statement expressions. */
+ append_to_statement_list_force (t, &cur_stmt_list);
+
+ return t;
+}
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)). An object declared as
@@ -344,17 +465,93 @@ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
void
c_print_identifier (FILE *file, tree node, int indent)
{
- print_node (file, "symbol", IDENTIFIER_SYMBOL_VALUE (node), indent + 4);
- print_node (file, "tag", IDENTIFIER_TAG_VALUE (node), indent + 4);
- print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
+ print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4);
+ print_node (file, "tag", I_TAG_DECL (node), indent + 4);
+ print_node (file, "label", I_LABEL_DECL (node), indent + 4);
if (C_IS_RESERVED_WORD (node))
{
tree rid = ridpointers[C_RID_CODE (node)];
indent_to (file, indent + 4);
- fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
+ fprintf (file, "rid %p \"%s\"",
(void *) rid, IDENTIFIER_POINTER (rid));
}
}
+
+/* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
+ which may be any of several kinds of DECL or TYPE or error_mark_node,
+ in the scope SCOPE. */
+static void
+bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
+{
+ struct c_binding *b, **here;
+
+ if (binding_freelist)
+ {
+ b = binding_freelist;
+ binding_freelist = b->prev;
+ }
+ else
+ b = GGC_NEW (struct c_binding);
+
+ b->shadowed = 0;
+ b->decl = decl;
+ b->id = name;
+ b->depth = scope->depth;
+ b->invisible = invisible;
+ b->nested = nested;
+ b->inner_comp = 0;
+
+ b->type = 0;
+
+ b->prev = scope->bindings;
+ scope->bindings = b;
+
+ if (!name)
+ return;
+
+ switch (TREE_CODE (decl))
+ {
+ case LABEL_DECL: here = &I_LABEL_BINDING (name); break;
+ case ENUMERAL_TYPE:
+ case UNION_TYPE:
+ case RECORD_TYPE: here = &I_TAG_BINDING (name); break;
+ case VAR_DECL:
+ case FUNCTION_DECL:
+ case TYPE_DECL:
+ case CONST_DECL:
+ case PARM_DECL:
+ case ERROR_MARK: here = &I_SYMBOL_BINDING (name); break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Locate the appropriate place in the chain of shadowed decls
+ to insert this binding. Normally, scope == current_scope and
+ this does nothing. */
+ while (*here && (*here)->depth > scope->depth)
+ here = &(*here)->shadowed;
+
+ b->shadowed = *here;
+ *here = b;
+}
+
+/* Clear the binding structure B, stick it on the binding_freelist,
+ and return the former value of b->prev. This is used by pop_scope
+ and get_parm_info to iterate destructively over all the bindings
+ from a given scope. */
+static struct c_binding *
+free_binding_and_advance (struct c_binding *b)
+{
+ struct c_binding *prev = b->prev;
+
+ memset (b, 0, sizeof (struct c_binding));
+ b->prev = binding_freelist;
+ binding_freelist = b;
+
+ return prev;
+}
+
/* Hook called at end of compilation to assume 1 elt
for a file-scope tentative array defn that wasn't complete before. */
@@ -367,56 +564,22 @@ c_finish_incomplete_decl (tree decl)
tree type = TREE_TYPE (decl);
if (type != error_mark_node
&& TREE_CODE (type) == ARRAY_TYPE
- && ! DECL_EXTERNAL (decl)
+ && !DECL_EXTERNAL (decl)
&& TYPE_DOMAIN (type) == 0)
{
- warning ("%Jarray '%D' assumed to have one element", decl, decl);
+ warning (0, "array %q+D assumed to have one element", decl);
- complete_array_type (type, NULL_TREE, 1);
+ complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
layout_decl (decl, 0);
}
}
}
-/* Reuse or create a struct for this scope. */
-
-static struct c_scope *
-make_scope (void)
-{
- struct c_scope *result;
- if (scope_freelist)
- {
- result = scope_freelist;
- scope_freelist = result->outer;
- }
- else
- result = ggc_alloc_cleared (sizeof (struct c_scope));
-
- return result;
-}
-
-/* Remove the topmost scope from the stack and add it to the
- free list, updating current_function_scope if necessary. */
-
-static void
-pop_scope (void)
-{
- struct c_scope *scope = current_scope;
-
- current_scope = scope->outer;
- if (scope->function_body)
- current_function_scope = scope->outer_function;
-
- memset (scope, 0, sizeof (struct c_scope));
- scope->outer = scope_freelist;
- scope_freelist = scope;
-}
-
/* The Objective-C front-end often needs to determine the current scope. */
void *
-get_current_scope (void)
+objc_get_current_scope (void)
{
return current_scope;
}
@@ -428,30 +591,27 @@ void
objc_mark_locals_volatile (void *enclosing_blk)
{
struct c_scope *scope;
+ struct c_binding *b;
for (scope = current_scope;
scope && scope != enclosing_blk;
scope = scope->outer)
{
- tree decl;
+ for (b = scope->bindings; b; b = b->prev)
+ objc_volatilize_decl (b->decl);
- for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
- {
- DECL_REGISTER (decl) = 0;
- TREE_THIS_VOLATILE (decl) = 1;
- }
/* Do not climb up past the current function. */
if (scope->function_body)
break;
}
}
-/* Nonzero if we are currently in the global scope. */
+/* Nonzero if we are currently in file scope. */
int
global_bindings_p (void)
{
- return current_scope == global_scope;
+ return current_scope == file_scope && !c_override_global_bindings_to_false;
}
void
@@ -468,19 +628,8 @@ declare_parm_level (void)
current_scope->parm_flag = true;
}
-/* Nonzero if currently making parm declarations. */
-
-int
-in_parm_level_p (void)
-{
- return current_scope->parm_flag;
-}
-
-/* Enter a new scope. The dummy parameter is for signature
- compatibility with lang_hooks.decls.pushlevel. */
-
void
-pushlevel (int dummy ATTRIBUTE_UNUSED)
+push_scope (void)
{
if (next_is_function_body)
{
@@ -505,49 +654,58 @@ pushlevel (int dummy ATTRIBUTE_UNUSED)
}
else
{
- struct c_scope *scope = make_scope ();
+ struct c_scope *scope;
+ if (scope_freelist)
+ {
+ scope = scope_freelist;
+ scope_freelist = scope->outer;
+ }
+ else
+ scope = GGC_CNEW (struct c_scope);
scope->keep = keep_next_level_flag;
scope->outer = current_scope;
+ scope->depth = current_scope ? (current_scope->depth + 1) : 0;
+
+ /* Check for scope depth overflow. Unlikely (2^28 == 268,435,456) but
+ possible. */
+ if (current_scope && scope->depth == 0)
+ {
+ scope->depth--;
+ sorry ("GCC supports only %u nested scopes", scope->depth);
+ }
+
current_scope = scope;
keep_next_level_flag = false;
}
}
-/* Exit a scope. Restore the state of the identifier-decl mappings
- that were in effect when this scope was entered.
-
- If KEEP is KEEP_YES (1), this scope had explicit declarations, so
- create a BLOCK node to record its declarations and subblocks for
- debugging output. If KEEP is KEEP_MAYBE, do so only if the names
- or tags lists are nonempty.
-
- The second parameter is ignored; it is present only for
- signature compatibility with lang_hooks.decls.poplevel.
+/* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT. */
- If FUNCTIONBODY is nonzero, this level is the body of a function,
- even if current_scope->function_body is not set. This is used
- by language-independent code that generates synthetic functions,
- and cannot set current_scope->function_body.
+static void
+set_type_context (tree type, tree context)
+{
+ for (type = TYPE_MAIN_VARIANT (type); type;
+ type = TYPE_NEXT_VARIANT (type))
+ TYPE_CONTEXT (type) = context;
+}
- FIXME: Eliminate the need for all arguments. */
+/* Exit a scope. Restore the state of the identifier-decl mappings
+ that were in effect when this scope was entered. Return a BLOCK
+ node containing all the DECLs in this scope that are of interest
+ to debug info generation. */
tree
-poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
+pop_scope (void)
{
struct c_scope *scope = current_scope;
- tree block;
- tree decl;
- tree p;
+ tree block, context, p;
+ struct c_binding *b;
- /* The following line does not use |= due to a bug in HP's C compiler. */
- scope->function_body = scope->function_body | functionbody;
+ bool functionbody = scope->function_body;
+ bool keep = functionbody || scope->keep || scope->bindings;
- if (keep == KEEP_MAYBE)
- keep = (scope->names || scope->tags);
-
- keep |= scope->keep;
- keep |= scope->function_body;
+ c_end_vm_scope (scope->depth);
/* If appropriate, create a BLOCK to record the decls for the life
of this function. */
@@ -555,128 +713,170 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
if (keep)
{
block = make_node (BLOCK);
- BLOCK_VARS (block) = scope->names;
BLOCK_SUBBLOCKS (block) = scope->blocks;
TREE_USED (block) = 1;
- }
- /* In each subblock, record that this is its superior. */
- for (p = scope->blocks; p; p = TREE_CHAIN (p))
- BLOCK_SUPERCONTEXT (p) = block;
+ /* In each subblock, record that this is its superior. */
+ for (p = scope->blocks; p; p = TREE_CHAIN (p))
+ BLOCK_SUPERCONTEXT (p) = block;
- /* Clear out the variable bindings in this scope.
+ BLOCK_VARS (block) = 0;
+ }
- Propagate TREE_ADDRESSABLE from nested functions to their
- containing functions.
+ /* The TYPE_CONTEXTs for all of the tagged types belonging to this
+ scope must be set so that they point to the appropriate
+ construct, i.e. either to the current FUNCTION_DECL node, or
+ else to the BLOCK node we just constructed.
- Issue warnings for unused variables and labels, and errors for
- undefined labels, if there are any. */
+ Note that for tagged types whose scope is just the formal
+ parameter list for some function type specification, we can't
+ properly set their TYPE_CONTEXTs here, because we don't have a
+ pointer to the appropriate FUNCTION_TYPE node readily available
+ to us. For those cases, the TYPE_CONTEXTs of the relevant tagged
+ type nodes get set in `grokdeclarator' as soon as we have created
+ the FUNCTION_TYPE node which will represent the "scope" for these
+ "parameter list local" tagged types. */
+ if (scope->function_body)
+ context = current_function_decl;
+ else if (scope == file_scope)
+ {
+ tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0);
+ TREE_CHAIN (file_decl) = all_translation_units;
+ all_translation_units = file_decl;
+ context = file_decl;
+ }
+ else
+ context = block;
- for (p = scope->names; p; p = TREE_CHAIN (p))
+ /* Clear all bindings in this scope. */
+ for (b = scope->bindings; b; b = free_binding_and_advance (b))
{
+ p = b->decl;
switch (TREE_CODE (p))
{
case LABEL_DECL:
+ /* Warnings for unused labels, errors for undefined labels. */
if (TREE_USED (p) && !DECL_INITIAL (p))
{
- error ("%Jlabel `%D' used but not defined", p, p);
+ error ("label %q+D used but not defined", p);
DECL_INITIAL (p) = error_mark_node;
}
else if (!TREE_USED (p) && warn_unused_label)
{
if (DECL_INITIAL (p))
- warning ("%Jlabel `%D' defined but not used", p, p);
+ warning (0, "label %q+D defined but not used", p);
else
- warning ("%Jlabel `%D' declared but not defined", p, p);
+ warning (0, "label %q+D declared but not defined", p);
}
+ /* Labels go in BLOCK_VARS. */
+ TREE_CHAIN (p) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = p;
+ gcc_assert (I_LABEL_BINDING (b->id) == b);
+ I_LABEL_BINDING (b->id) = b->shadowed;
+ break;
+
+ case ENUMERAL_TYPE:
+ case UNION_TYPE:
+ case RECORD_TYPE:
+ set_type_context (p, context);
- IDENTIFIER_LABEL_VALUE (DECL_NAME (p)) = 0;
+ /* Types may not have tag-names, in which case the type
+ appears in the bindings list with b->id NULL. */
+ if (b->id)
+ {
+ gcc_assert (I_TAG_BINDING (b->id) == b);
+ I_TAG_BINDING (b->id) = b->shadowed;
+ }
break;
case FUNCTION_DECL:
- if (! TREE_ASM_WRITTEN (p)
+ /* Propagate TREE_ADDRESSABLE from nested functions to their
+ containing functions. */
+ if (!TREE_ASM_WRITTEN (p)
&& DECL_INITIAL (p) != 0
&& TREE_ADDRESSABLE (p)
&& DECL_ABSTRACT_ORIGIN (p) != 0
&& DECL_ABSTRACT_ORIGIN (p) != p)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
- goto normal;
+ if (!DECL_EXTERNAL (p)
+ && DECL_INITIAL (p) == 0)
+ {
+ error ("nested function %q+D declared but never defined", p);
+ undef_nested_function = true;
+ }
+ goto common_symbol;
case VAR_DECL:
- /* Keep this in sync with stmt.c:warn_about_unused_variables.
- No warnings when the global scope is popped because the
- global scope isn't popped for the last translation unit,
- so the warnings are done in c_write_global_declaration. */
- if (warn_unused_variable && scope != global_scope
- && !TREE_USED (p)
+ /* Warnings for unused variables. */
+ if (!TREE_USED (p)
+ && !TREE_NO_WARNING (p)
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
- && !DECL_ARTIFICIAL (p))
- warning ("%Junused variable `%D'", p, p);
- /* fall through */
+ && !DECL_ARTIFICIAL (p)
+ && scope != file_scope
+ && scope != external_scope)
+ warning (OPT_Wunused_variable, "unused variable %q+D", p);
- default:
- normal:
- if (DECL_NAME (p))
+ if (b->inner_comp)
{
- if (DECL_EXTERNAL (p) && scope != global_scope)
- /* External decls stay in the symbol-value slot but are
- inaccessible. */
- C_DECL_INVISIBLE (p) = 1;
- else
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0;
+ error ("type of array %q+D completed incompatibly with"
+ " implicit initialization", p);
}
- break;
- }
- }
-
- /* Clear out the parameter bindings in this scope, if any.
- Unused-parameter warnings are handled by function.c. */
- for (p = scope->parms; p; p = TREE_CHAIN (p))
- if (DECL_NAME (p))
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0;
-
- /* Clear out the tag-meanings declared in this scope.
- Set the TYPE_CONTEXTs for all of the tagged types belonging to
- this scope so that they point to the appropriate construct, i.e.
- either to the current FUNCTION_DECL node, or else to the BLOCK
- node we just constructed.
+ /* Fall through. */
+ case TYPE_DECL:
+ case CONST_DECL:
+ common_symbol:
+ /* All of these go in BLOCK_VARS, but only if this is the
+ binding in the home scope. */
+ if (!b->nested)
+ {
+ TREE_CHAIN (p) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = p;
+ }
+ /* If this is the file scope, and we are processing more
+ than one translation unit in this compilation, set
+ DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
+ This makes same_translation_unit_p work, and causes
+ static declarations to be given disambiguating suffixes. */
+ if (scope == file_scope && num_in_fnames > 1)
+ {
+ DECL_CONTEXT (p) = context;
+ if (TREE_CODE (p) == TYPE_DECL)
+ set_type_context (TREE_TYPE (p), context);
+ }
- Note that for tagged types whose scope is just the formal
- parameter list for some function type specification, we can't
- properly set their TYPE_CONTEXTs here, because we don't have a
- pointer to the appropriate FUNCTION_TYPE node readily available
- to us. For those cases, the TYPE_CONTEXTs of the relevant tagged
- type nodes get set in `grokdeclarator' as soon as we have created
- the FUNCTION_TYPE node which will represent the "scope" for these
- "parameter list local" tagged types. */
+ /* Fall through. */
+ /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
+ already been put there by store_parm_decls. Unused-
+ parameter warnings are handled by function.c.
+ error_mark_node obviously does not go in BLOCK_VARS and
+ does not get unused-variable warnings. */
+ case PARM_DECL:
+ case ERROR_MARK:
+ /* It is possible for a decl not to have a name. We get
+ here with b->id NULL in this case. */
+ if (b->id)
+ {
+ gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+ I_SYMBOL_BINDING (b->id) = b->shadowed;
+ if (b->shadowed && b->shadowed->type)
+ TREE_TYPE (b->shadowed->decl) = b->shadowed->type;
+ }
+ break;
- decl = scope->function_body ? current_function_decl : block;
- for (p = scope->tags; p; p = TREE_CHAIN (p))
- {
- if (TREE_PURPOSE (p))
- IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = 0;
- if (decl)
- TYPE_CONTEXT (TREE_VALUE (p)) = decl;
+ default:
+ gcc_unreachable ();
+ }
}
- /* Restore all name- and label-meanings from outer scopes that were
- shadowed by this scope. */
- for (p = scope->shadowed; p; p = TREE_CHAIN (p))
- if (TREE_VALUE (p) && TREE_CODE (TREE_VALUE (p)) == LABEL_DECL)
- IDENTIFIER_LABEL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
- else
- IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
-
- /* Restore all tag-meanings from outer scopes that were shadowed by
- this scope. */
- for (p = scope->shadowed_tags; p; p = TREE_CHAIN (p))
- IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
/* Dispose of the block that we just made inside some higher level. */
- if (scope->function_body && current_function_decl)
- DECL_INITIAL (current_function_decl) = block;
+ if ((scope->function_body || scope == file_scope) && context)
+ {
+ DECL_INITIAL (context) = block;
+ BLOCK_SUPERCONTEXT (block) = context;
+ }
else if (scope->outer)
{
if (block)
@@ -689,11 +889,64 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
}
/* Pop the current scope, and free the structure for reuse. */
- pop_scope ();
+ current_scope = scope->outer;
+ if (scope->function_body)
+ current_function_scope = scope->outer_function;
+
+ memset (scope, 0, sizeof (struct c_scope));
+ scope->outer = scope_freelist;
+ scope_freelist = scope;
return block;
}
+void
+push_file_scope (void)
+{
+ tree decl;
+
+ if (file_scope)
+ return;
+
+ push_scope ();
+ file_scope = current_scope;
+
+ start_fname_decls ();
+
+ for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
+ bind (DECL_NAME (decl), decl, file_scope,
+ /*invisible=*/false, /*nested=*/true);
+}
+
+void
+pop_file_scope (void)
+{
+ /* In case there were missing closebraces, get us back to the global
+ binding level. */
+ while (current_scope != file_scope)
+ pop_scope ();
+
+ /* __FUNCTION__ is defined at file scope (""). This
+ call may not be necessary as my tests indicate it
+ still works without it. */
+ finish_fname_decls ();
+
+ /* This is the point to write out a PCH if we're doing that.
+ In that case we do not want to do anything else. */
+ if (pch_file)
+ {
+ c_common_write_pch ();
+ return;
+ }
+
+ /* Pop off the file scope and close this translation unit. */
+ pop_scope ();
+ file_scope = 0;
+
+ maybe_apply_pending_pragma_weaks ();
+ cgraph_finalize_compilation_unit ();
+}
+
/* Insert BLOCK at the end of the list of subblocks of the current
scope. This is used when a BIND_EXPR is expanded, to handle the
BLOCK node inside the BIND_EXPR. */
@@ -704,15 +957,6 @@ insert_block (tree block)
TREE_USED (block) = 1;
SCOPE_LIST_APPEND (current_scope, blocks, block);
}
-
-/* Set the BLOCK node for the innermost scope (the one we are
- currently in). The RTL expansion machinery requires us to provide
- this hook, but it is not useful in function-at-a-time mode. */
-
-void
-set_block (tree block ATTRIBUTE_UNUSED)
-{
-}
/* Push a definition or a declaration of struct, union or enum tag "name".
"type" should be the type node.
@@ -721,24 +965,13 @@ set_block (tree block ATTRIBUTE_UNUSED)
Note that the definition may really be just a forward reference.
In that case, the TYPE_SIZE will be zero. */
-void
+static void
pushtag (tree name, tree type)
{
- struct c_scope *b = current_scope;
-
/* Record the identifier as the type's name if it has none. */
- if (name)
- {
- if (TYPE_NAME (type) == 0)
- TYPE_NAME (type) = name;
-
- if (IDENTIFIER_TAG_VALUE (name))
- b->shadowed_tags = tree_cons (name, IDENTIFIER_TAG_VALUE (name),
- b->shadowed_tags);
- IDENTIFIER_TAG_VALUE (name) = type;
- }
-
- b->tags = tree_cons (name, type, b->tags);
+ if (name && !TYPE_NAME (type))
+ TYPE_NAME (type) = name;
+ bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false);
/* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
tagged type we just added to the current scope. This fake
@@ -750,7 +983,7 @@ pushtag (tree name, tree type)
TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
/* An approximation for now, so we can tell this is a function-scope tag.
- This will be updated in poplevel. */
+ This will be updated in pop_scope. */
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
}
@@ -778,10 +1011,10 @@ match_builtin_function_types (tree newtype, tree oldtype)
while (oldargs || newargs)
{
- if (! oldargs
- || ! newargs
- || ! TREE_VALUE (oldargs)
- || ! TREE_VALUE (newargs)
+ if (!oldargs
+ || !newargs
+ || !TREE_VALUE (oldargs)
+ || !TREE_VALUE (newargs)
|| TYPE_MODE (TREE_VALUE (oldargs))
!= TYPE_MODE (TREE_VALUE (newargs)))
return 0;
@@ -794,9 +1027,9 @@ match_builtin_function_types (tree newtype, tree oldtype)
return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
}
-/* Subroutine of diagnose_mismathed_decls. Check for function type
+/* Subroutine of diagnose_mismatched_decls. Check for function type
mismatch involving an empty arglist vs a nonempty one and give clearer
- diagnostics. */
+ diagnostics. */
static void
diagnose_arglist_conflict (tree newdecl, tree olddecl,
tree newtype, tree oldtype)
@@ -804,7 +1037,7 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl,
tree t;
if (TREE_CODE (olddecl) != FUNCTION_DECL
- || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype), COMPARE_STRICT)
+ || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype))
|| !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0)
||
(TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0)))
@@ -820,14 +1053,14 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl,
if (TREE_CHAIN (t) == 0
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
- inform ("a parameter list with an ellipsis can't match "
+ inform ("a parameter list with an ellipsis can%'t match "
"an empty parameter name list declaration");
break;
}
if (c_type_promotes_to (type) != type)
{
- inform ("an argument type that has a default promotion can't match "
+ inform ("an argument type that has a default promotion can%'t match "
"an empty parameter name list declaration");
break;
}
@@ -844,8 +1077,7 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
tree newargs, oldargs;
int i;
- /* ??? Elsewhere TYPE_MAIN_VARIANT is not used in this context. */
-#define END_OF_ARGLIST(t) (TYPE_MAIN_VARIANT (t) == void_type_node)
+#define END_OF_ARGLIST(t) ((t) == void_type_node)
oldargs = TYPE_ACTUAL_ARG_TYPES (oldtype);
newargs = TYPE_ARG_TYPES (newtype);
@@ -856,6 +1088,12 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
tree oldargtype = TREE_VALUE (oldargs);
tree newargtype = TREE_VALUE (newargs);
+ if (oldargtype == error_mark_node || newargtype == error_mark_node)
+ return false;
+
+ oldargtype = TYPE_MAIN_VARIANT (oldargtype);
+ newargtype = TYPE_MAIN_VARIANT (newargtype);
+
if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
break;
@@ -863,23 +1101,24 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
agree on the number of arguments. */
if (END_OF_ARGLIST (oldargtype))
{
- error ("%Jprototype for '%D' declares more arguments "
- "than previous old-style definition", newdecl, newdecl);
+ error ("prototype for %q+D declares more arguments "
+ "than previous old-style definition", newdecl);
return false;
}
else if (END_OF_ARGLIST (newargtype))
{
- error ("%Jprototype for '%D' declares fewer arguments "
- "than previous old-style definition", newdecl, newdecl);
+ error ("prototype for %q+D declares fewer arguments "
+ "than previous old-style definition", newdecl);
return false;
}
/* Type for passing arg must be consistent with that declared
for the arg. */
- else if (! comptypes (oldargtype, newargtype, COMPARE_STRICT))
+ else if (!comptypes (oldargtype, newargtype))
{
- error ("%Jprototype for '%D' declares arg %d with incompatible type",
- newdecl, newdecl, i);
+ error ("prototype for %q+D declares argument %d"
+ " with incompatible type",
+ newdecl, i);
return false;
}
@@ -890,8 +1129,8 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
/* If we get here, no errors were found, but do issue a warning
for this poor-style construct. */
- warning ("%Jprototype for '%D' follows non-prototype definition",
- newdecl, newdecl);
+ warning (0, "prototype for %q+D follows non-prototype definition",
+ newdecl);
return true;
#undef END_OF_ARGLIST
}
@@ -900,16 +1139,16 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
first in a pair of mismatched declarations, using the diagnostic
function DIAG. */
static void
-locate_old_decl (tree decl, void (*diag)(const char *, ...))
+locate_old_decl (tree decl, void (*diag)(const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2))
{
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
;
else if (DECL_INITIAL (decl))
- diag (N_("%Jprevious definition of '%D' was here"), decl, decl);
+ diag (G_("previous definition of %q+D was here"), decl);
else if (C_DECL_IMPLICIT (decl))
- diag (N_("%Jprevious implicit declaration of '%D' was here"), decl, decl);
+ diag (G_("previous implicit declaration of %q+D was here"), decl);
else
- diag (N_("%Jprevious declaration of '%D' was here"), decl, decl);
+ diag (G_("previous declaration of %q+D was here"), decl);
}
/* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL.
@@ -927,6 +1166,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
tree newtype, oldtype;
bool pedwarned = false;
bool warned = false;
+ bool retval = true;
+
+#define DECL_EXTERN_INLINE(DECL) (DECL_DECLARED_INLINE_P (DECL) \
+ && DECL_EXTERNAL (DECL))
/* If we have error_mark_node for either decl or type, just discard
the previous decl - we're in an error cascade already. */
@@ -941,19 +1184,19 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
unless OLDDECL is a builtin. OLDDECL will be discarded in any case. */
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
- if (TREE_CODE (olddecl) != FUNCTION_DECL
- || !DECL_BUILT_IN (olddecl) || !C_DECL_INVISIBLE (olddecl))
+ if (!(TREE_CODE (olddecl) == FUNCTION_DECL
+ && DECL_BUILT_IN (olddecl)
+ && !C_DECL_DECLARED_BUILTIN (olddecl)))
{
- error ("%J'%D' redeclared as different kind of symbol",
- newdecl, newdecl);
+ error ("%q+D redeclared as different kind of symbol", newdecl);
locate_old_decl (olddecl, error);
}
else if (TREE_PUBLIC (newdecl))
- warning ("%Jbuilt-in function '%D' declared as non-function",
- newdecl, newdecl);
- else if (warn_shadow)
- warning ("%Jshadowing built-in function '%D'",
- newdecl, newdecl);
+ warning (0, "built-in function %q+D declared as non-function",
+ newdecl);
+ else
+ warning (OPT_Wshadow, "declaration of %q+D shadows "
+ "a built-in function", newdecl);
return false;
}
@@ -961,34 +1204,34 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
given scope. */
if (TREE_CODE (olddecl) == CONST_DECL)
{
- error ("%Jredeclaration of enumerator `%D'", newdecl, newdecl);
+ error ("redeclaration of enumerator %q+D", newdecl);
locate_old_decl (olddecl, error);
return false;
}
- if (!comptypes (oldtype, newtype, COMPARE_STRICT))
+ if (!comptypes (oldtype, newtype))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN (olddecl) && C_DECL_INVISIBLE (olddecl))
+ && DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
{
/* Accept harmless mismatch in function types.
This is for the ffs and fprintf builtins. */
tree trytype = match_builtin_function_types (newtype, oldtype);
- if (trytype && comptypes (newtype, trytype, COMPARE_STRICT))
+ if (trytype && comptypes (newtype, trytype))
*oldtypep = oldtype = trytype;
else
{
/* If types don't match for a built-in, throw away the
built-in. No point in calling locate_old_decl here, it
- won't print anything. */
- warning ("%Jconflicting types for built-in function '%D'",
- newdecl, newdecl);
+ won't print anything. */
+ warning (0, "conflicting types for built-in function %q+D",
+ newdecl);
return false;
}
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_SOURCE_LINE (olddecl) == 0)
+ && DECL_IS_BUILTIN (olddecl))
{
/* A conflicting function declaration for a predeclared
function that isn't actually built in. Objective C uses
@@ -1004,17 +1247,32 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl)
&& TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
- && C_FUNCTION_IMPLICIT_INT (newdecl))
+ && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl))
{
- pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl);
+ pedwarn ("conflicting types for %q+D", newdecl);
/* Make sure we keep void as the return type. */
TREE_TYPE (newdecl) = *newtypep = newtype = oldtype;
C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
pedwarned = true;
}
+ /* Permit void foo (...) to match an earlier call to foo (...) with
+ no declared type (thus, implicitly int). */
+ else if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == void_type_node
+ && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node
+ && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl))
+ {
+ pedwarn ("conflicting types for %q+D", newdecl);
+ /* Make sure we keep void as the return type. */
+ TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype;
+ pedwarned = true;
+ }
else
{
- error ("%Jconflicting types for '%D'", newdecl, newdecl);
+ if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
+ error ("conflicting type qualifiers for %q+D", newdecl);
+ else
+ error ("conflicting types for %q+D", newdecl);
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
locate_old_decl (olddecl, error);
return false;
@@ -1027,9 +1285,9 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (TREE_CODE (newdecl) == TYPE_DECL)
{
if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
- return true; /* allow OLDDECL to continue in use */
-
- error ("%Jredefinition of typedef '%D'", newdecl, newdecl);
+ return true; /* Allow OLDDECL to continue in use. */
+
+ error ("redefinition of typedef %q+D", newdecl);
locate_old_decl (olddecl, error);
return false;
}
@@ -1040,6 +1298,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
Multiple definitions are not allowed (6.9p3,5) but GCC permits
two definitions if one is 'extern inline' and one is not. The non-
extern-inline definition supersedes the extern-inline definition. */
+
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* If you declare a built-in function name as static, or
@@ -1047,28 +1306,39 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
can't validate the argument list) the built-in definition is
overridden, but optionally warn this was a bad choice of name. */
if (DECL_BUILT_IN (olddecl)
- && C_DECL_INVISIBLE (olddecl)
+ && !C_DECL_DECLARED_BUILTIN (olddecl)
&& (!TREE_PUBLIC (newdecl)
|| (DECL_INITIAL (newdecl)
&& !TYPE_ARG_TYPES (TREE_TYPE (newdecl)))))
{
- if (warn_shadow)
- warning ("%Jshadowing built-in function '%D'", newdecl, newdecl);
+ warning (OPT_Wshadow, "declaration of %q+D shadows "
+ "a built-in function", newdecl);
/* Discard the old built-in function. */
return false;
}
-
+
if (DECL_INITIAL (newdecl))
{
- if (DECL_INITIAL (olddecl)
- && !(DECL_DECLARED_INLINE_P (olddecl)
- && DECL_EXTERNAL (olddecl)
- && !(DECL_DECLARED_INLINE_P (newdecl)
- && DECL_EXTERNAL (newdecl))))
+ if (DECL_INITIAL (olddecl))
{
- error ("%Jredefinition of '%D'", newdecl, newdecl);
- locate_old_decl (olddecl, error);
- return false;
+ /* If both decls are in the same TU and the new declaration
+ isn't overriding an extern inline reject the new decl.
+ When we handle c99 style inline rules we'll want to reject
+ the following:
+
+ DECL_EXTERN_INLINE (olddecl)
+ && !DECL_EXTERN_INLINE (newdecl)
+
+ if they're in the same translation unit. Until we implement
+ the full semantics we accept the construct. */
+ if (!(DECL_EXTERN_INLINE (olddecl)
+ && !DECL_EXTERN_INLINE (newdecl))
+ && same_translation_unit_p (newdecl, olddecl))
+ {
+ error ("redefinition of %q+D", newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
}
}
/* If we have a prototype after an old-style function definition,
@@ -1081,47 +1351,67 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
locate_old_decl (olddecl, error);
return false;
}
- /* Mismatched non-static and static is considered poor style.
- We only diagnose static then non-static if -Wtraditional,
- because it is the most convenient way to get some effects
- (see e.g. what unwind-dw2-fde-glibc.c does to the definition
- of _Unwind_Find_FDE in unwind-dw2-fde.c). Revisit? */
+ /* A non-static declaration (even an "extern") followed by a
+ static declaration is undefined behavior per C99 6.2.2p3-5,7.
+ The same is true for a static forward declaration at block
+ scope followed by a non-static declaration/definition at file
+ scope. Static followed by non-static at the same scope is
+ not undefined behavior, and is the most convenient way to get
+ some effects (see e.g. what unwind-dw2-fde-glibc.c does to
+ the definition of _Unwind_Find_FDE in unwind-dw2-fde.c), but
+ we do diagnose it if -Wtraditional. */
if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
{
- /* A static function declaration for a predeclared function
- that isn't actually built in, silently overrides the
- default. Objective C uses these. See also above.
- FIXME: Make Objective C use normal builtins. */
- if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_SOURCE_LINE (olddecl) == 0)
- return false;
- else
+ /* Two exceptions to the rule. If olddecl is an extern
+ inline, or a predeclared function that isn't actually
+ built in, newdecl silently overrides olddecl. The latter
+ occur only in Objective C; see also above. (FIXME: Make
+ Objective C use normal builtins.) */
+ if (!DECL_IS_BUILTIN (olddecl)
+ && !DECL_EXTERN_INLINE (olddecl))
{
- warning ("%Jstatic declaration of '%D' follows "
- "non-static declaration", newdecl, newdecl);
- warned = true;
+ error ("static declaration of %q+D follows "
+ "non-static declaration", newdecl);
+ locate_old_decl (olddecl, error);
}
+ return false;
}
- else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl)
- && warn_traditional)
+ else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl))
{
- warning ("%Jnon-static declaration of '%D' follows "
- "static declaration", newdecl, newdecl);
- warned = true;
+ if (DECL_CONTEXT (olddecl))
+ {
+ error ("non-static declaration of %q+D follows "
+ "static declaration", newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
+ else if (warn_traditional)
+ {
+ warning (OPT_Wtraditional, "non-static declaration of %q+D "
+ "follows static declaration", newdecl);
+ warned = true;
+ }
}
}
else if (TREE_CODE (newdecl) == VAR_DECL)
{
/* Only variables can be thread-local, and all declarations must
agree on this property. */
- if (DECL_THREAD_LOCAL (newdecl) != DECL_THREAD_LOCAL (olddecl))
+ if (C_DECL_THREADPRIVATE_P (olddecl) && !DECL_THREAD_LOCAL_P (newdecl))
+ {
+ /* Nothing to check. Since OLDDECL is marked threadprivate
+ and NEWDECL does not have a thread-local attribute, we
+ will merge the threadprivate attribute into NEWDECL. */
+ ;
+ }
+ else if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl))
{
- if (DECL_THREAD_LOCAL (newdecl))
- error ("%Jthread-local declaration of '%D' follows "
- "non-thread-local declaration", newdecl, newdecl);
+ if (DECL_THREAD_LOCAL_P (newdecl))
+ error ("thread-local declaration of %q+D follows "
+ "non-thread-local declaration", newdecl);
else
- error ("%Jnon-thread-local declaration of '%D' follows "
- "thread-local declaration", newdecl, newdecl);
+ error ("non-thread-local declaration of %q+D follows "
+ "thread-local declaration", newdecl);
locate_old_decl (olddecl, error);
return false;
@@ -1130,25 +1420,46 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* Multiple initialized definitions are not allowed (6.9p3,5). */
if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
{
- error ("%Jredefinition of '%D'", newdecl, newdecl);
+ error ("redefinition of %q+D", newdecl);
locate_old_decl (olddecl, error);
return false;
}
- /* Objects declared at file scope: if at least one is 'extern',
- it's fine (6.2.2p4); otherwise the linkage must agree (6.2.2p7). */
- if (DECL_FILE_SCOPE_P (newdecl))
+ /* Objects declared at file scope: if the first declaration had
+ external linkage (even if it was an external reference) the
+ second must have external linkage as well, or the behavior is
+ undefined. If the first declaration had internal linkage, then
+ the second must too, or else be an external reference (in which
+ case the composite declaration still has internal linkage).
+ As for function declarations, we warn about the static-then-
+ extern case only for -Wtraditional. See generally 6.2.2p3-5,7. */
+ if (DECL_FILE_SCOPE_P (newdecl)
+ && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
{
- if (!DECL_EXTERNAL (newdecl)
- && !DECL_EXTERNAL (olddecl)
- && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
+ if (DECL_EXTERNAL (newdecl))
+ {
+ if (!DECL_FILE_SCOPE_P (olddecl))
+ {
+ error ("extern declaration of %q+D follows "
+ "declaration with no linkage", newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
+ else if (warn_traditional)
+ {
+ warning (OPT_Wtraditional, "non-static declaration of %q+D "
+ "follows static declaration", newdecl);
+ warned = true;
+ }
+ }
+ else
{
if (TREE_PUBLIC (newdecl))
- error ("%Jnon-static declaration of '%D' follows "
- "static declaration", newdecl, newdecl);
+ error ("non-static declaration of %q+D follows "
+ "static declaration", newdecl);
else
- error ("%Jstatic declaration of '%D' follows "
- "non-static declaration", newdecl, newdecl);
+ error ("static declaration of %q+D follows "
+ "non-static declaration", newdecl);
locate_old_decl (olddecl, error);
return false;
@@ -1156,32 +1467,37 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
/* Two objects with the same name declared at the same block
scope must both be external references (6.7p3). */
- else if (DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl)
- && (!DECL_EXTERNAL (newdecl) || !DECL_EXTERNAL (olddecl)))
+ else if (!DECL_FILE_SCOPE_P (newdecl))
{
if (DECL_EXTERNAL (newdecl))
- error ("%Jextern declaration of '%D' follows "
- "declaration with no linkage", newdecl, newdecl);
+ {
+ /* Extern with initializer at block scope, which will
+ already have received an error. */
+ }
else if (DECL_EXTERNAL (olddecl))
- error ("%Jdeclaration of '%D' with no linkage follows "
- "extern declaration", newdecl, newdecl);
+ {
+ error ("declaration of %q+D with no linkage follows "
+ "extern declaration", newdecl);
+ locate_old_decl (olddecl, error);
+ }
else
- error ("%Jredeclaration of '%D' with no linkage",
- newdecl, newdecl);
+ {
+ error ("redeclaration of %q+D with no linkage", newdecl);
+ locate_old_decl (olddecl, error);
+ }
- locate_old_decl (olddecl, error);
return false;
}
}
/* warnings */
- /* All decls must agree on a non-default visibility. */
- if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
- && DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT
+ /* All decls must agree on a visibility. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS)
+ && DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
- warning ("%Jredeclaration of '%D' with different visibility "
- "(old visibility preserved)", newdecl, newdecl);
+ warning (0, "redeclaration of %q+D with different visibility "
+ "(old visibility preserved)", newdecl);
warned = true;
}
@@ -1191,70 +1507,56 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warning ("%Jinline declaration of '%D' follows "
- "declaration with attribute noinline", newdecl, newdecl);
+ warning (OPT_Wattributes, "inline declaration of %qD follows "
+ "declaration with attribute noinline", newdecl);
warned = true;
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warning ("%Jdeclaration of '%D' with attribute noinline follows "
- "inline declaration ", newdecl, newdecl);
+ warning (OPT_Wattributes, "declaration of %q+D with attribute "
+ "noinline follows inline declaration ", newdecl);
warned = true;
}
/* Inline declaration after use or definition.
??? Should we still warn about this now we have unit-at-a-time
- mode and can get it right? */
- if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl))
+ mode and can get it right?
+ Definitely don't complain if the decls are in different translation
+ units. */
+ if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)
+ && same_translation_unit_p (olddecl, newdecl))
{
if (TREE_USED (olddecl))
{
- warning ("%J'%D' declared inline after being called",
- olddecl, olddecl);
+ warning (0, "%q+D declared inline after being called", olddecl);
warned = true;
}
else if (DECL_INITIAL (olddecl))
{
- warning ("%J'%D' declared inline after its definition",
- olddecl, olddecl);
+ warning (0, "%q+D declared inline after its definition", olddecl);
warned = true;
}
}
}
else /* PARM_DECL, VAR_DECL */
{
- /* Redeclaration of a PARM_DECL is invalid unless this is the
- real position of a forward-declared parameter (GCC extension). */
+ /* Redeclaration of a parameter is a constraint violation (this is
+ not explicitly stated, but follows from C99 6.7p3 [no more than
+ one declaration of the same identifier with no linkage in the
+ same scope, except type tags] and 6.2.2p6 [parameters have no
+ linkage]). We must check for a forward parameter declaration,
+ indicated by TREE_ASM_WRITTEN on the old declaration - this is
+ an extension, the mandatory diagnostic for which is handled by
+ mark_forward_parm_decls. */
+
if (TREE_CODE (newdecl) == PARM_DECL
&& (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
{
- error ("%Jredefinition of parameter '%D'", newdecl, newdecl);
+ error ("redefinition of parameter %q+D", newdecl);
locate_old_decl (olddecl, error);
return false;
}
-
- /* These bits are only type qualifiers when applied to objects. */
- if (TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
- {
- if (TREE_THIS_VOLATILE (newdecl))
- pedwarn ("%Jvolatile declaration of '%D' follows "
- "non-volatile declaration", newdecl, newdecl);
- else
- pedwarn ("%Jnon-volatile declaration of '%D' follows "
- "volatile declaration", newdecl, newdecl);
- pedwarned = true;
- }
- if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl))
- {
- if (TREE_READONLY (newdecl))
- pedwarn ("%Jconst declaration of '%D' follows "
- "non-const declaration", newdecl, newdecl);
- else
- pedwarn ("%Jnon-const declaration of '%D' follows "
- "const declaration", newdecl, newdecl);
- pedwarned = true;
- }
}
/* Optional warning for completely redundant decls. */
@@ -1264,11 +1566,11 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
definition. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
- /* Don't warn about redundant redeclarations of builtins. */
+ /* Don't warn about redundant redeclarations of builtins. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL
&& !DECL_BUILT_IN (newdecl)
&& DECL_BUILT_IN (olddecl)
- && C_DECL_INVISIBLE (olddecl))
+ && !C_DECL_DECLARED_BUILTIN (olddecl))
/* Don't warn about an extern followed by a definition. */
&& !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl))
/* Don't warn about forward parameter decls. */
@@ -1278,15 +1580,18 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
&& !(TREE_CODE (newdecl) == VAR_DECL
&& DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl)))
{
- warning ("%Jredundant redeclaration of '%D'", newdecl, newdecl);
+ warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D",
+ newdecl);
warned = true;
}
/* Report location of previous decl/defn in a consistent manner. */
if (warned || pedwarned)
- locate_old_decl (olddecl, pedwarned ? pedwarn : warning);
+ locate_old_decl (olddecl, pedwarned ? pedwarn : warning0);
- return true;
+#undef DECL_EXTERN_INLINE
+
+ return retval;
}
/* Subroutine of duplicate_decls. NEWDECL has been found to be
@@ -1299,26 +1604,43 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
{
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != 0);
-
- /* For real parm decl following a forward decl, return 1 so old decl
- will be reused. Only allow this to happen once. */
+ int new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
+ && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
+ int old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
+ && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
+
+ /* For real parm decl following a forward decl, rechain the old decl
+ in its new location and clear TREE_ASM_WRITTEN (it's not a
+ forward decl anymore). */
if (TREE_CODE (newdecl) == PARM_DECL
- && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
+ && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
{
+ struct c_binding *b, **here;
+
+ for (here = &current_scope->bindings; *here; here = &(*here)->prev)
+ if ((*here)->decl == olddecl)
+ goto found;
+ gcc_unreachable ();
+
+ found:
+ b = *here;
+ *here = b->prev;
+ b->prev = current_scope->bindings;
+ current_scope->bindings = b;
+
TREE_ASM_WRITTEN (olddecl) = 0;
- return;
}
DECL_ATTRIBUTES (newdecl)
- = (*targetm.merge_decl_attributes) (olddecl, newdecl);
+ = targetm.merge_decl_attributes (olddecl, newdecl);
/* Merge the data types specified in the two decls. */
TREE_TYPE (newdecl)
= TREE_TYPE (olddecl)
- = common_type (newtype, oldtype);
+ = composite_type (newtype, oldtype);
/* Lay the type out, unless already done. */
- if (oldtype != TREE_TYPE (newdecl))
+ if (!comptypes (oldtype, TREE_TYPE (newdecl)))
{
if (TREE_TYPE (newdecl) != error_mark_node)
layout_type (TREE_TYPE (newdecl));
@@ -1341,76 +1663,93 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
}
}
- /* Keep the old rtl since we can safely use it. */
- COPY_DECL_RTL (olddecl, newdecl);
/* Merge the type qualifiers. */
if (TREE_READONLY (newdecl))
TREE_READONLY (olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl))
- {
- TREE_THIS_VOLATILE (olddecl) = 1;
- if (TREE_CODE (newdecl) == VAR_DECL)
- make_var_volatile (newdecl);
- }
-
- /* Keep source location of definition rather than declaration. */
- if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
+ TREE_THIS_VOLATILE (olddecl) = 1;
+
+ /* Merge deprecatedness. */
+ if (TREE_DEPRECATED (newdecl))
+ TREE_DEPRECATED (olddecl) = 1;
+
+ /* Keep source location of definition rather than declaration and of
+ prototype rather than non-prototype unless that prototype is
+ built-in. */
+ if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
+ || (old_is_prototype && !new_is_prototype
+ && !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
- /* Merge the unused-warning information. */
- if (DECL_IN_SYSTEM_HEADER (olddecl))
- DECL_IN_SYSTEM_HEADER (newdecl) = 1;
- else if (DECL_IN_SYSTEM_HEADER (newdecl))
- DECL_IN_SYSTEM_HEADER (olddecl) = 1;
-
/* Merge the initialization information. */
if (DECL_INITIAL (newdecl) == 0)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
- /* Merge the section attribute.
- We want to issue an error if the sections conflict but that must be
- done later in decl_attributes since we are called before attributes
- are assigned. */
- if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
- DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+ /* Merge the threadprivate attribute. */
+ if (TREE_CODE (olddecl) == VAR_DECL && C_DECL_THREADPRIVATE_P (olddecl))
+ {
+ DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
+ C_DECL_THREADPRIVATE_P (newdecl) = 1;
+ }
- /* Copy the assembler name.
- Currently, it can only be defined in the prototype. */
- COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
+ {
+ /* Merge the unused-warning information. */
+ if (DECL_IN_SYSTEM_HEADER (olddecl))
+ DECL_IN_SYSTEM_HEADER (newdecl) = 1;
+ else if (DECL_IN_SYSTEM_HEADER (newdecl))
+ DECL_IN_SYSTEM_HEADER (olddecl) = 1;
- /* If either declaration has a nondefault visibility, use it. */
- if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
- DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+ /* Merge the section attribute.
+ We want to issue an error if the sections conflict but that
+ must be done later in decl_attributes since we are called
+ before attributes are assigned. */
+ if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
+ DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
- DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
- DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
- DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
- |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
- TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
- TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
- DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
- DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
- }
+ /* Copy the assembler name.
+ Currently, it can only be defined in the prototype. */
+ COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
- /* Merge the storage class information. */
- merge_weak (newdecl, olddecl);
+ /* Use visibility of whichever declaration had it specified */
+ if (DECL_VISIBILITY_SPECIFIED (olddecl))
+ {
+ DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+ DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
+ }
- /* For functions, static overrides non-static. */
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
- /* This is since we don't automatically
- copy the attributes of NEWDECL into OLDDECL. */
- TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
- /* If this clears `static', clear it in the identifier too. */
- if (! TREE_PUBLIC (olddecl))
- TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ {
+ DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
+ DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
+ DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
+ DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
+ |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+ TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+ TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+ DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+ DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+ DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
+ }
+
+ /* Merge the storage class information. */
+ merge_weak (newdecl, olddecl);
+
+ /* For functions, static overrides non-static. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ {
+ TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
+ /* This is since we don't automatically
+ copy the attributes of NEWDECL into OLDDECL. */
+ TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+ /* If this clears `static', clear it in the identifier too. */
+ if (!TREE_PUBLIC (olddecl))
+ TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
+ }
}
+
if (DECL_EXTERNAL (newdecl))
{
TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
@@ -1418,7 +1757,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
/* An extern decl does not override previous storage class. */
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
- if (! DECL_EXTERNAL (newdecl))
+ if (!DECL_EXTERNAL (newdecl))
{
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
@@ -1434,13 +1773,13 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
{
/* If we're redefining a function previously defined as extern
inline, make sure we emit debug info for the inline before we
- throw it away, in case it was inlined into a function that hasn't
- been written out yet. */
+ throw it away, in case it was inlined into a function that
+ hasn't been written out yet. */
if (new_is_definition && DECL_INITIAL (olddecl))
{
if (TREE_USED (olddecl)
/* In unit-at-a-time mode we never inline re-defined extern
- inline functions. */
+ inline functions. */
&& !flag_unit_at_a_time
&& cgraph_function_possibly_inlined_p (olddecl))
(*debug_hooks->outlining_inline_function) (olddecl);
@@ -1451,8 +1790,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
}
else
{
- /* If either decl says `inline', this fn is inline,
- unless its definition was passed already. */
+ /* If either decl says `inline', this fn is inline, unless
+ its definition was passed already. */
if (DECL_DECLARED_INLINE_P (newdecl)
|| DECL_DECLARED_INLINE_P (olddecl))
DECL_DECLARED_INLINE_P (newdecl) = 1;
@@ -1463,23 +1802,30 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
if (DECL_BUILT_IN (olddecl))
{
- /* If redeclaring a builtin function, it stays built in. */
+ /* If redeclaring a builtin function, it stays built in.
+ But it gets tagged as having been declared. */
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+ C_DECL_DECLARED_BUILTIN (newdecl) = 1;
+ if (new_is_prototype)
+ C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+ else
+ C_DECL_BUILTIN_PROTOTYPE (newdecl)
+ = C_DECL_BUILTIN_PROTOTYPE (olddecl);
}
/* Also preserve various other info from the definition. */
- if (! new_is_definition)
+ if (!new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
- DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
+ DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
/* Set DECL_INLINE on the declaration if we've got a body
from which to instantiate. */
- if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
+ if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl))
{
DECL_INLINE (newdecl) = 1;
DECL_ABSTRACT_ORIGIN (newdecl)
@@ -1491,22 +1837,43 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
/* If a previous declaration said inline, mark the
definition as inlinable. */
if (DECL_DECLARED_INLINE_P (newdecl)
- && ! DECL_UNINLINABLE (newdecl))
+ && !DECL_UNINLINABLE (newdecl))
DECL_INLINE (newdecl) = 1;
}
}
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
- But preserve OLDDECL's DECL_UID and C_DECL_INVISIBLE. */
+ But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */
{
unsigned olddecl_uid = DECL_UID (olddecl);
- unsigned olddecl_invisible = C_DECL_INVISIBLE (olddecl);
+ tree olddecl_context = DECL_CONTEXT (olddecl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
- sizeof (struct tree_decl) - sizeof (struct tree_common));
+ sizeof (struct tree_decl_common) - sizeof (struct tree_common));
+ switch (TREE_CODE (olddecl))
+ {
+ case FIELD_DECL:
+ case VAR_DECL:
+ case PARM_DECL:
+ case LABEL_DECL:
+ case RESULT_DECL:
+ case CONST_DECL:
+ case TYPE_DECL:
+ case FUNCTION_DECL:
+ memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+ (char *) newdecl + sizeof (struct tree_decl_common),
+ tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common));
+ break;
+
+ default:
+
+ memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+ (char *) newdecl + sizeof (struct tree_decl_common),
+ sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common));
+ }
DECL_UID (olddecl) = olddecl_uid;
- C_DECL_INVISIBLE (olddecl) = olddecl_invisible;
+ DECL_CONTEXT (olddecl) = olddecl_context;
}
/* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
@@ -1516,7 +1883,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
&& (TREE_CODE (olddecl) == FUNCTION_DECL
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
- make_decl_rtl (olddecl, NULL);
+ make_decl_rtl (olddecl);
}
/* Handle when a new declaration NEWDECL has the same name as an old
@@ -1529,81 +1896,67 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
static bool
duplicate_decls (tree newdecl, tree olddecl)
{
- tree newtype, oldtype;
+ tree newtype = NULL, oldtype = NULL;
if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
- return false;
+ {
+ /* Avoid `unused variable' and other warnings warnings for OLDDECL. */
+ TREE_NO_WARNING (olddecl) = 1;
+ return false;
+ }
merge_decls (newdecl, olddecl, newtype, oldtype);
return true;
}
-
-
-/* Return any external DECL associated with ID, whether or not it is
- currently in scope. */
-
-static tree
-any_external_decl (tree id)
-{
- tree decl = IDENTIFIER_SYMBOL_VALUE (id);
- tree t;
-
- if (decl == 0 || TREE_CODE (decl) == ERROR_MARK)
- return 0;
- else if (TREE_CODE (decl) != TYPE_DECL && DECL_EXTERNAL (decl))
- return decl;
-
- t = purpose_member (id, truly_local_externals);
- if (t)
- return TREE_VALUE (t);
-
- return 0;
-}
-/* Record an external decl DECL. This only does something if a
- shadowing decl already exists. */
+
+/* Check whether decl-node NEW_DECL shadows an existing declaration. */
static void
-record_external_decl (tree decl)
+warn_if_shadowing (tree new_decl)
{
- tree name = DECL_NAME (decl);
- if (!IDENTIFIER_SYMBOL_VALUE (name))
- return;
-
- truly_local_externals = tree_cons (name, decl, truly_local_externals);
-}
+ struct c_binding *b;
-/* Check whether decl-node X shadows an existing declaration.
- OLD is the old IDENTIFIER_SYMBOL_VALUE of the DECL_NAME of X,
- which might be a NULL_TREE. */
-static void
-warn_if_shadowing (tree x, tree old)
-{
- /* Nothing to shadow? */
- if (old == 0
- /* Shadow warnings not wanted? */
- || !warn_shadow
+ /* Shadow warnings wanted? */
+ if (!warn_shadow
/* No shadow warnings for internally generated vars. */
- || DECL_SOURCE_LINE (x) == 0
+ || DECL_IS_BUILTIN (new_decl)
/* No shadow warnings for vars made for inlining. */
- || DECL_FROM_INLINE (x)
- /* Don't warn about the parm names in function declarator
- within a function declarator.
- It would be nice to avoid warning in any function
- declarator in a declaration, as opposed to a definition,
- but there is no way to tell it's not a definition. */
- || (TREE_CODE (x) == PARM_DECL && current_scope->outer->parm_flag)
- /* Shadow warnings only apply to local variables and parameters. */
- || (TREE_CODE (x) != PARM_DECL && DECL_FILE_SCOPE_P (x)))
+ || DECL_FROM_INLINE (new_decl))
return;
- if (TREE_CODE (old) == PARM_DECL)
- warning ("%Jdeclaration of '%D' shadows a parameter", x, x);
- else if (DECL_FILE_SCOPE_P (old))
- warning ("%Jdeclaration of '%D' shadows a global declaration", x, x);
- else
- warning ("%Jdeclaration of '%D' shadows a previous local", x, x);
+ /* Is anything being shadowed? Invisible decls do not count. */
+ for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
+ if (b->decl && b->decl != new_decl && !b->invisible)
+ {
+ tree old_decl = b->decl;
- warning ("%Jshadowed declaration is here", old);
+ if (old_decl == error_mark_node)
+ {
+ warning (OPT_Wshadow, "declaration of %q+D shadows previous "
+ "non-variable", new_decl);
+ break;
+ }
+ else if (TREE_CODE (old_decl) == PARM_DECL)
+ warning (OPT_Wshadow, "declaration of %q+D shadows a parameter",
+ new_decl);
+ else if (DECL_FILE_SCOPE_P (old_decl))
+ warning (OPT_Wshadow, "declaration of %q+D shadows a global "
+ "declaration", new_decl);
+ else if (TREE_CODE (old_decl) == FUNCTION_DECL
+ && DECL_BUILT_IN (old_decl))
+ {
+ warning (OPT_Wshadow, "declaration of %q+D shadows "
+ "a built-in function", new_decl);
+ break;
+ }
+ else
+ warning (OPT_Wshadow, "declaration of %q+D shadows a previous local",
+ new_decl);
+
+ warning (OPT_Wshadow, "%Jshadowed declaration is here", old_decl);
+
+ break;
+ }
}
@@ -1623,7 +1976,7 @@ warn_if_shadowing (tree x, tree old)
translation and get back the corresponding typedef name. For
example, given:
- typedef struct S MY_TYPE;
+ typedef struct S MY_TYPE;
MY_TYPE object;
Later parts of the compiler might only know that `object' was of
@@ -1654,7 +2007,7 @@ warn_if_shadowing (tree x, tree old)
static void
clone_underlying_type (tree x)
{
- if (DECL_SOURCE_LINE (x) == 0)
+ if (DECL_IS_BUILTIN (x))
{
if (TYPE_NAME (TREE_TYPE (x)) == 0)
TYPE_NAME (TREE_TYPE (x)) = x;
@@ -1664,7 +2017,7 @@ clone_underlying_type (tree x)
{
tree tt = TREE_TYPE (x);
DECL_ORIGINAL_TYPE (x) = tt;
- tt = build_type_copy (tt);
+ tt = build_variant_type_copy (tt);
TYPE_NAME (tt) = x;
TREE_USED (tt) = TREE_USED (x);
TREE_TYPE (x) = tt;
@@ -1684,134 +2037,253 @@ pushdecl (tree x)
{
tree name = DECL_NAME (x);
struct c_scope *scope = current_scope;
-
-#ifdef ENABLE_CHECKING
- if (error_mark_node == 0)
- /* Called too early. */
- abort ();
-#endif
+ struct c_binding *b;
+ bool nested = false;
/* Functions need the lang_decl data. */
- if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
- DECL_LANG_SPECIFIC (x) = ggc_alloc_cleared (sizeof (struct lang_decl));
-
- /* A local extern declaration for a function doesn't constitute nesting.
- A local auto declaration does, since it's a forward decl
- for a nested function coming later. */
- if (current_function_decl == NULL
- || ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
- && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x)))
- DECL_CONTEXT (x) = current_file_decl;
- else
+ if (TREE_CODE (x) == FUNCTION_DECL && !DECL_LANG_SPECIFIC (x))
+ DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
+
+ /* Must set DECL_CONTEXT for everything not at file scope or
+ DECL_FILE_SCOPE_P won't work. Local externs don't count
+ unless they have initializers (which generate code). */
+ if (current_function_decl
+ && ((TREE_CODE (x) != FUNCTION_DECL && TREE_CODE (x) != VAR_DECL)
+ || DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
DECL_CONTEXT (x) = current_function_decl;
- if (name)
- {
- tree old;
-
- if (warn_nested_externs
- && scope != global_scope
- && DECL_EXTERNAL (x)
- && !DECL_IN_SYSTEM_HEADER (x))
- warning ("nested extern declaration of `%s'",
- IDENTIFIER_POINTER (name));
-
- old = lookup_name_current_level (name);
- if (old && duplicate_decls (x, old))
+ /* If this is of variably modified type, prevent jumping into its
+ scope. */
+ if ((TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == TYPE_DECL)
+ && variably_modified_type_p (TREE_TYPE (x), NULL_TREE))
+ c_begin_vm_scope (scope->depth);
+
+ /* Anonymous decls are just inserted in the scope. */
+ if (!name)
+ {
+ bind (name, x, scope, /*invisible=*/false, /*nested=*/false);
+ return x;
+ }
+
+ /* First, see if there is another declaration with the same name in
+ the current scope. If there is, duplicate_decls may do all the
+ work for us. If duplicate_decls returns false, that indicates
+ two incompatible decls in the same scope; we are to silently
+ replace the old one (duplicate_decls has issued all appropriate
+ diagnostics). In particular, we should not consider possible
+ duplicates in the external scope, or shadowing. */
+ b = I_SYMBOL_BINDING (name);
+ if (b && B_IN_SCOPE (b, scope))
+ {
+ struct c_binding *b_ext, *b_use;
+ tree type = TREE_TYPE (x);
+ tree visdecl = b->decl;
+ tree vistype = TREE_TYPE (visdecl);
+ if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+ && COMPLETE_TYPE_P (TREE_TYPE (x)))
+ b->inner_comp = false;
+ b_use = b;
+ b_ext = b;
+ /* If this is an external linkage declaration, we should check
+ for compatibility with the type in the external scope before
+ setting the type at this scope based on the visible
+ information only. */
+ if (TREE_PUBLIC (x) && TREE_PUBLIC (visdecl))
{
- /* For PARM_DECLs, old may be a forward declaration.
- If so, we want to remove it from its old location
- (in the variables chain) and rechain it in the
- location given by the new declaration. */
- if (TREE_CODE (x) == PARM_DECL)
+ while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
+ b_ext = b_ext->shadowed;
+ if (b_ext)
{
- tree *p;
- for (p = &scope->names; *p; p = &TREE_CHAIN (*p))
- if (*p == old)
- {
- *p = TREE_CHAIN (old);
- SCOPE_LIST_APPEND (scope, parms, old);
- break;
- }
+ b_use = b_ext;
+ if (b_use->type)
+ TREE_TYPE (b_use->decl) = b_use->type;
}
- return old;
}
- if (DECL_EXTERNAL (x) || scope == global_scope)
+ if (duplicate_decls (x, b_use->decl))
{
- /* Find and check against a previous, not-in-scope, external
- decl for this identifier. (C99 6.2.7p2: All declarations
- that refer to the same object or function shall have
- compatible type; otherwise, the behavior is undefined.) */
- tree ext = any_external_decl (name);
- if (ext)
+ if (b_use != b)
{
- if (duplicate_decls (x, ext))
- x = copy_node (ext);
+ /* Save the updated type in the external scope and
+ restore the proper type for this scope. */
+ tree thistype;
+ if (comptypes (vistype, type))
+ thistype = composite_type (vistype, type);
+ else
+ thistype = TREE_TYPE (b_use->decl);
+ b_use->type = TREE_TYPE (b_use->decl);
+ if (TREE_CODE (b_use->decl) == FUNCTION_DECL
+ && DECL_BUILT_IN (b_use->decl))
+ thistype
+ = build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES
+ (b_use->type));
+ TREE_TYPE (b_use->decl) = thistype;
}
- else
- record_external_decl (x);
+ return b_use->decl;
}
+ else
+ goto skip_external_and_shadow_checks;
+ }
+
+ /* All declarations with external linkage, and all external
+ references, go in the external scope, no matter what scope is
+ current. However, the binding in that scope is ignored for
+ purposes of normal name lookup. A separate binding structure is
+ created in the requested scope; this governs the normal
+ visibility of the symbol.
+
+ The binding in the externals scope is used exclusively for
+ detecting duplicate declarations of the same object, no matter
+ what scope they are in; this is what we do here. (C99 6.2.7p2:
+ All declarations that refer to the same object or function shall
+ have compatible type; otherwise, the behavior is undefined.) */
+ if (DECL_EXTERNAL (x) || scope == file_scope)
+ {
+ tree type = TREE_TYPE (x);
+ tree vistype = 0;
+ tree visdecl = 0;
+ bool type_saved = false;
+ if (b && !B_IN_EXTERNAL_SCOPE (b)
+ && (TREE_CODE (b->decl) == FUNCTION_DECL
+ || TREE_CODE (b->decl) == VAR_DECL)
+ && DECL_FILE_SCOPE_P (b->decl))
+ {
+ visdecl = b->decl;
+ vistype = TREE_TYPE (visdecl);
+ }
+ if (scope != file_scope
+ && !DECL_IN_SYSTEM_HEADER (x))
+ warning (OPT_Wnested_externs, "nested extern declaration of %qD", x);
- if (TREE_CODE (x) == TYPE_DECL)
- clone_underlying_type (x);
-
- /* If storing a local value, there may already be one
- (inherited). If so, record it for restoration when this
- scope ends. Take care not to do this if we are replacing an
- older decl in the same scope (i.e. duplicate_decls returned
- false, above). */
- if (scope != global_scope)
+ while (b && !B_IN_EXTERNAL_SCOPE (b))
{
- tree inherited_decl = lookup_name (name);
- if (inherited_decl && inherited_decl != old)
+ /* If this decl might be modified, save its type. This is
+ done here rather than when the decl is first bound
+ because the type may change after first binding, through
+ being completed or through attributes being added. If we
+ encounter multiple such decls, only the first should have
+ its type saved; the others will already have had their
+ proper types saved and the types will not have changed as
+ their scopes will not have been re-entered. */
+ if (DECL_P (b->decl) && DECL_FILE_SCOPE_P (b->decl) && !type_saved)
+ {
+ b->type = TREE_TYPE (b->decl);
+ type_saved = true;
+ }
+ if (B_IN_FILE_SCOPE (b)
+ && TREE_CODE (b->decl) == VAR_DECL
+ && TREE_STATIC (b->decl)
+ && TREE_CODE (TREE_TYPE (b->decl)) == ARRAY_TYPE
+ && !TYPE_DOMAIN (TREE_TYPE (b->decl))
+ && TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type)
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+ && !integer_zerop (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
{
- warn_if_shadowing (x, inherited_decl);
- scope->shadowed = tree_cons (name, inherited_decl,
- scope->shadowed);
+ /* Array type completed in inner scope, which should be
+ diagnosed if the completion does not have size 1 and
+ it does not get completed in the file scope. */
+ b->inner_comp = true;
}
+ b = b->shadowed;
}
- /* Install the new declaration in the requested scope. */
- IDENTIFIER_SYMBOL_VALUE (name) = x;
- C_DECL_INVISIBLE (x) = 0;
-
- /* If x's type is incomplete because it's based on a
- structure or union which has not yet been fully declared,
- attach it to that structure or union type, so we can go
- back and complete the variable declaration later, if the
- structure or union gets fully declared.
-
- If the input is erroneous, we can have error_mark in the type
- slot (e.g. "f(void a, ...)") - that doesn't count as an
- incomplete type. */
- if (TREE_TYPE (x) != error_mark_node
- && !COMPLETE_TYPE_P (TREE_TYPE (x)))
+ /* If a matching external declaration has been found, set its
+ type to the composite of all the types of that declaration.
+ After the consistency checks, it will be reset to the
+ composite of the visible types only. */
+ if (b && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
+ && b->type)
+ TREE_TYPE (b->decl) = b->type;
+
+ /* The point of the same_translation_unit_p check here is,
+ we want to detect a duplicate decl for a construct like
+ foo() { extern bar(); } ... static bar(); but not if
+ they are in different translation units. In any case,
+ the static does not go in the externals scope. */
+ if (b
+ && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
+ && duplicate_decls (x, b->decl))
{
- tree element = TREE_TYPE (x);
-
- while (TREE_CODE (element) == ARRAY_TYPE)
- element = TREE_TYPE (element);
- element = TYPE_MAIN_VARIANT (element);
-
- if ((TREE_CODE (element) == RECORD_TYPE
- || TREE_CODE (element) == UNION_TYPE)
- && (TREE_CODE (x) != TYPE_DECL
- || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
- && !COMPLETE_TYPE_P (element))
- C_TYPE_INCOMPLETE_VARS (element)
- = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
+ tree thistype;
+ if (vistype)
+ {
+ if (comptypes (vistype, type))
+ thistype = composite_type (vistype, type);
+ else
+ thistype = TREE_TYPE (b->decl);
+ }
+ else
+ thistype = type;
+ b->type = TREE_TYPE (b->decl);
+ if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
+ thistype
+ = build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES (b->type));
+ TREE_TYPE (b->decl) = thistype;
+ bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
+ return b->decl;
+ }
+ else if (TREE_PUBLIC (x))
+ {
+ if (visdecl && !b && duplicate_decls (x, visdecl))
+ {
+ /* An external declaration at block scope referring to a
+ visible entity with internal linkage. The composite
+ type will already be correct for this scope, so we
+ just need to fall through to make the declaration in
+ this scope. */
+ nested = true;
+ x = visdecl;
+ }
+ else
+ {
+ bind (name, x, external_scope, /*invisible=*/true,
+ /*nested=*/false);
+ nested = true;
+ }
}
}
- if (TREE_CODE (x) == PARM_DECL)
- SCOPE_LIST_APPEND (scope, parms, x);
- else
- SCOPE_LIST_APPEND (scope, names, x);
+ if (TREE_CODE (x) != PARM_DECL)
+ warn_if_shadowing (x);
+
+ skip_external_and_shadow_checks:
+ if (TREE_CODE (x) == TYPE_DECL)
+ clone_underlying_type (x);
+
+ bind (name, x, scope, /*invisible=*/false, nested);
+
+ /* If x's type is incomplete because it's based on a
+ structure or union which has not yet been fully declared,
+ attach it to that structure or union type, so we can go
+ back and complete the variable declaration later, if the
+ structure or union gets fully declared.
+
+ If the input is erroneous, we can have error_mark in the type
+ slot (e.g. "f(void a, ...)") - that doesn't count as an
+ incomplete type. */
+ if (TREE_TYPE (x) != error_mark_node
+ && !COMPLETE_TYPE_P (TREE_TYPE (x)))
+ {
+ tree element = TREE_TYPE (x);
+
+ while (TREE_CODE (element) == ARRAY_TYPE)
+ element = TREE_TYPE (element);
+ element = TYPE_MAIN_VARIANT (element);
+ if ((TREE_CODE (element) == RECORD_TYPE
+ || TREE_CODE (element) == UNION_TYPE)
+ && (TREE_CODE (x) != TYPE_DECL
+ || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
+ && !COMPLETE_TYPE_P (element))
+ C_TYPE_INCOMPLETE_VARS (element)
+ = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
+ }
return x;
}
-/* Record X as belonging to the global scope (C99 "file scope").
+/* Record X as belonging to file scope.
This is used only internally by the Objective-C front end,
and is limited to its needs. duplicate_decls is not called;
if there is any preexisting decl for this identifier, it is an ICE. */
@@ -1820,50 +2292,117 @@ tree
pushdecl_top_level (tree x)
{
tree name;
-
- if (TREE_CODE (x) != VAR_DECL)
- abort ();
+ bool nested = false;
+ gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL);
name = DECL_NAME (x);
- if (IDENTIFIER_SYMBOL_VALUE (name))
- abort ();
+ gcc_assert (TREE_CODE (x) == CONST_DECL || !I_SYMBOL_BINDING (name));
- DECL_CONTEXT (x) = current_file_decl;
- IDENTIFIER_SYMBOL_VALUE (name) = x;
+ if (TREE_PUBLIC (x))
+ {
+ bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
+ nested = true;
+ }
+ if (file_scope)
+ bind (name, x, file_scope, /*invisible=*/false, nested);
- SCOPE_LIST_APPEND (global_scope, names, x);
return x;
}
+static void
+implicit_decl_warning (tree id, tree olddecl)
+{
+ void (*diag) (const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2);
+ switch (mesg_implicit_function_declaration)
+ {
+ case 0: return;
+ case 1: diag = warning0; break;
+ case 2: diag = error; break;
+ default: gcc_unreachable ();
+ }
+
+ diag (G_("implicit declaration of function %qE"), id);
+ if (olddecl)
+ locate_old_decl (olddecl, diag);
+}
+
/* Generate an implicit declaration for identifier FUNCTIONID as a
function of type int (). */
tree
implicitly_declare (tree functionid)
{
- tree decl = any_external_decl (functionid);
+ struct c_binding *b;
+ tree decl = 0;
+ tree asmspec_tree;
- if (decl)
+ for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed)
{
- /* Implicit declaration of a function already declared
- (somehow) in a different scope, or as a built-in.
- If this is the first time this has happened, warn;
- then recycle the old declaration. */
- if (!C_DECL_IMPLICIT (decl))
+ if (B_IN_SCOPE (b, external_scope))
{
- implicit_decl_warning (DECL_NAME (decl));
- if (! DECL_FILE_SCOPE_P (decl))
- warning ("%Jprevious declaration of '%D'", decl, decl);
- C_DECL_IMPLICIT (decl) = 1;
+ decl = b->decl;
+ break;
}
- /* If this function is global, then it must already be in the
- global scope, so there's no need to push it again. */
- if (current_scope == global_scope)
+ }
+
+ if (decl)
+ {
+ if (decl == error_mark_node)
return decl;
- /* If this is a local declaration, make a copy; we can't have
- the same DECL listed in two different scopes. */
- return pushdecl (copy_node (decl));
+
+ /* FIXME: Objective-C has weird not-really-builtin functions
+ which are supposed to be visible automatically. They wind up
+ in the external scope because they're pushed before the file
+ scope gets created. Catch this here and rebind them into the
+ file scope. */
+ if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
+ {
+ bind (functionid, decl, file_scope,
+ /*invisible=*/false, /*nested=*/true);
+ return decl;
+ }
+ else
+ {
+ tree newtype = default_function_type;
+ if (b->type)
+ TREE_TYPE (decl) = b->type;
+ /* Implicit declaration of a function already declared
+ (somehow) in a different scope, or as a built-in.
+ If this is the first time this has happened, warn;
+ then recycle the old declaration but with the new type. */
+ if (!C_DECL_IMPLICIT (decl))
+ {
+ implicit_decl_warning (functionid, decl);
+ C_DECL_IMPLICIT (decl) = 1;
+ }
+ if (DECL_BUILT_IN (decl))
+ {
+ newtype = build_type_attribute_variant (newtype,
+ TYPE_ATTRIBUTES
+ (TREE_TYPE (decl)));
+ if (!comptypes (newtype, TREE_TYPE (decl)))
+ {
+ warning (0, "incompatible implicit declaration of built-in"
+ " function %qD", decl);
+ newtype = TREE_TYPE (decl);
+ }
+ }
+ else
+ {
+ if (!comptypes (newtype, TREE_TYPE (decl)))
+ {
+ error ("incompatible implicit declaration of function %qD",
+ decl);
+ locate_old_decl (decl, error);
+ }
+ }
+ b->type = TREE_TYPE (decl);
+ TREE_TYPE (decl) = newtype;
+ bind (functionid, decl, current_scope,
+ /*invisible=*/false, /*nested=*/true);
+ return decl;
+ }
}
/* Not seen before. */
@@ -1871,14 +2410,17 @@ implicitly_declare (tree functionid)
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
C_DECL_IMPLICIT (decl) = 1;
- implicit_decl_warning (functionid);
+ implicit_decl_warning (functionid, 0);
+ asmspec_tree = maybe_apply_renaming_pragma (decl, /*asmname=*/NULL);
+ if (asmspec_tree)
+ set_user_assembler_name (decl, TREE_STRING_POINTER (asmspec_tree));
/* C89 says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */
decl = pushdecl (decl);
/* No need to call objc_check_decl here - it's a function type. */
- rest_of_decl_compilation (decl, NULL, 0, 0);
+ rest_of_decl_compilation (decl, 0, 0);
/* Write a record describing this implicit function declaration
to the prototypes file (if requested). */
@@ -1890,51 +2432,38 @@ implicitly_declare (tree functionid)
return decl;
}
-static void
-implicit_decl_warning (tree id)
-{
- const char *name = IDENTIFIER_POINTER (id);
- if (mesg_implicit_function_declaration == 2)
- error ("implicit declaration of function `%s'", name);
- else if (mesg_implicit_function_declaration == 1)
- warning ("implicit declaration of function `%s'", name);
-}
-
/* Issue an error message for a reference to an undeclared variable
ID, including a reference to a builtin outside of function-call
context. Establish a binding of the identifier to error_mark_node
in an appropriate scope, which will suppress further errors for the
- same identifier. */
+ same identifier. The error message should be given location LOC. */
void
-undeclared_variable (tree id)
+undeclared_variable (tree id, location_t loc)
{
static bool already = false;
struct c_scope *scope;
if (current_function_decl == 0)
{
- error ("`%s' undeclared here (not in a function)",
- IDENTIFIER_POINTER (id));
+ error ("%H%qE undeclared here (not in a function)", &loc, id);
scope = current_scope;
}
else
{
- error ("`%s' undeclared (first use in this function)",
- IDENTIFIER_POINTER (id));
+ error ("%H%qE undeclared (first use in this function)", &loc, id);
- if (! already)
+ if (!already)
{
- error ("(Each undeclared identifier is reported only once");
- error ("for each function it appears in.)");
+ error ("%H(Each undeclared identifier is reported only once", &loc);
+ error ("%Hfor each function it appears in.)", &loc);
already = true;
}
- scope = current_function_scope;
+ /* If we are parsing old-style parameter decls, current_function_decl
+ will be nonnull but current_function_scope will be null. */
+ scope = current_function_scope ? current_function_scope : current_scope;
}
-
- scope->shadowed = tree_cons (id, IDENTIFIER_SYMBOL_VALUE (id),
- scope->shadowed);
- IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node;
+ bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false);
}
/* Subroutine of lookup_label, declare_label, define_label: construct a
@@ -1952,20 +2481,6 @@ make_label (tree name, location_t location)
return label;
}
-/* Another subroutine of lookup_label, declare_label, define_label:
- set up the binding of name to LABEL_DECL in the given SCOPE. */
-
-static void
-bind_label (tree name, tree label, struct c_scope *scope)
-{
- if (IDENTIFIER_LABEL_VALUE (name))
- scope->shadowed = tree_cons (name, IDENTIFIER_LABEL_VALUE (name),
- scope->shadowed);
- IDENTIFIER_LABEL_VALUE (name) = label;
-
- SCOPE_LIST_APPEND (scope, names, label);
-}
-
/* Get the LABEL_DECL corresponding to identifier NAME as a label.
Create one if none exists so far for the current function.
This is called when a label is used in a goto expression or
@@ -1978,15 +2493,14 @@ lookup_label (tree name)
if (current_function_decl == 0)
{
- error ("label %s referenced outside of any function",
- IDENTIFIER_POINTER (name));
+ error ("label %qE referenced outside of any function", name);
return 0;
}
/* Use a label already defined or ref'd with this name, but not if
it is inherited from a containing function and wasn't declared
using __label__. */
- label = IDENTIFIER_LABEL_VALUE (name);
+ label = I_LABEL_DECL (name);
if (label && (DECL_CONTEXT (label) == current_function_decl
|| C_DECLARED_LABEL_FLAG (label)))
{
@@ -2002,7 +2516,8 @@ lookup_label (tree name)
label = make_label (name, input_location);
/* Ordinary labels go in the current function scope. */
- bind_label (name, label, current_function_scope);
+ bind (name, label, current_function_scope,
+ /*invisible=*/false, /*nested=*/false);
return label;
}
@@ -2010,33 +2525,29 @@ lookup_label (tree name)
any that may be inherited from containing functions or containing
scopes. This is called for __label__ declarations. */
-/* Note that valid use, if the label being shadowed comes from another
- scope in the same function, requires calling declare_nonlocal_label
- right away. (Is this still true? -zw 2003-07-17) */
-
tree
declare_label (tree name)
{
- tree label = IDENTIFIER_LABEL_VALUE (name);
- tree dup;
+ struct c_binding *b = I_LABEL_BINDING (name);
+ tree label;
/* Check to make sure that the label hasn't already been declared
at this scope */
- for (dup = current_scope->names; dup; dup = TREE_CHAIN (dup))
- if (dup == label)
- {
- error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
- error ("%Jthis is a previous declaration", dup);
+ if (b && B_IN_CURRENT_SCOPE (b))
+ {
+ error ("duplicate label declaration %qE", name);
+ locate_old_decl (b->decl, error);
- /* Just use the previous declaration. */
- return dup;
- }
+ /* Just use the previous declaration. */
+ return b->decl;
+ }
label = make_label (name, input_location);
C_DECLARED_LABEL_FLAG (label) = 1;
/* Declared labels go in the current scope. */
- bind_label (name, label, current_scope);
+ bind (name, label, current_scope,
+ /*invisible=*/false, /*nested=*/false);
return label;
}
@@ -2047,13 +2558,12 @@ declare_label (tree name)
tree
define_label (location_t location, tree name)
{
- tree label;
-
/* Find any preexisting label with this name. It is an error
if that label has already been defined in this function, or
if there is a containing function with a declared label with
the same name. */
- label = IDENTIFIER_LABEL_VALUE (name);
+ tree label = I_LABEL_DECL (name);
+ struct c_label_list *nlist_se, *nlist_vm;
if (label
&& ((DECL_CONTEXT (label) == current_function_decl
@@ -2061,11 +2571,8 @@ define_label (location_t location, tree name)
|| (DECL_CONTEXT (label) != current_function_decl
&& C_DECLARED_LABEL_FLAG (label))))
{
- error ("%Hduplicate label `%D'", &location, label);
- if (DECL_INITIAL (label))
- error ("%J`%D' previously defined here", label, label);
- else
- error ("%J`%D' previously declared here", label, label);
+ error ("%Hduplicate label %qD", &location, label);
+ locate_old_decl (label, error);
return 0;
}
else if (label && DECL_CONTEXT (label) == current_function_decl)
@@ -2073,6 +2580,11 @@ define_label (location_t location, tree name)
/* The label has been used or declared already in this function,
but not defined. Update its location to point to this
definition. */
+ if (C_DECL_UNDEFINABLE_STMT_EXPR (label))
+ error ("%Jjump into statement expression", label);
+ if (C_DECL_UNDEFINABLE_VM (label))
+ error ("%Jjump into scope of identifier with variably modified type",
+ label);
DECL_SOURCE_LOCATION (label) = location;
}
else
@@ -2081,28 +2593,29 @@ define_label (location_t location, tree name)
label = make_label (name, location);
/* Ordinary labels go in the current function scope. */
- bind_label (name, label, current_function_scope);
+ bind (name, label, current_function_scope,
+ /*invisible=*/false, /*nested=*/false);
}
- if (warn_traditional && !in_system_header && lookup_name (name))
- warning ("%Htraditional C lacks a separate namespace for labels, "
- "identifier `%s' conflicts", &location,
- IDENTIFIER_POINTER (name));
+ if (!in_system_header && lookup_name (name))
+ warning (OPT_Wtraditional, "%Htraditional C lacks a separate namespace "
+ "for labels, identifier %qE conflicts", &location, name);
+
+ nlist_se = XOBNEW (&parser_obstack, struct c_label_list);
+ nlist_se->next = label_context_stack_se->labels_def;
+ nlist_se->label = label;
+ label_context_stack_se->labels_def = nlist_se;
+
+ nlist_vm = XOBNEW (&parser_obstack, struct c_label_list);
+ nlist_vm->next = label_context_stack_vm->labels_def;
+ nlist_vm->label = label;
+ label_context_stack_vm->labels_def = nlist_vm;
/* Mark label as having been defined. */
DECL_INITIAL (label) = error_mark_node;
return label;
}
-/* Return the list of declarations of the current scope. */
-
-tree
-getdecls (void)
-{
- return current_scope->names;
-}
-
-
/* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name.
If THISLEVEL_ONLY is nonzero, searches only the current_scope.
@@ -2113,25 +2626,29 @@ getdecls (void)
static tree
lookup_tag (enum tree_code code, tree name, int thislevel_only)
{
- tree tag = IDENTIFIER_TAG_VALUE (name);
+ struct c_binding *b = I_TAG_BINDING (name);
int thislevel = 0;
- if (!tag)
+ if (!b || !b->decl)
return 0;
/* We only care about whether it's in this level if
thislevel_only was set or it might be a type clash. */
- if (thislevel_only || TREE_CODE (tag) != code)
- {
- if (current_scope == global_scope
- || purpose_member (name, current_scope->tags))
+ if (thislevel_only || TREE_CODE (b->decl) != code)
+ {
+ /* For our purposes, a tag in the external scope is the same as
+ a tag in the file scope. (Primarily relevant to Objective-C
+ and its builtin structure tags, which get pushed before the
+ file scope is created.) */
+ if (B_IN_CURRENT_SCOPE (b)
+ || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
thislevel = 1;
}
if (thislevel_only && !thislevel)
return 0;
- if (TREE_CODE (tag) != code)
+ if (TREE_CODE (b->decl) != code)
{
/* Definition isn't the kind we were looking for. */
pending_invalid_xref = name;
@@ -2144,7 +2661,7 @@ lookup_tag (enum tree_code code, tree name, int thislevel_only)
if (thislevel)
pending_xref_error ();
}
- return tag;
+ return b->decl;
}
/* Print an error message now
@@ -2156,9 +2673,8 @@ void
pending_xref_error (void)
{
if (pending_invalid_xref != 0)
- error ("%H`%s' defined as wrong kind of tag",
- &pending_invalid_xref_location,
- IDENTIFIER_POINTER (pending_invalid_xref));
+ error ("%H%qE defined as wrong kind of tag",
+ &pending_invalid_xref_location, pending_invalid_xref);
pending_invalid_xref = 0;
}
@@ -2171,36 +2687,22 @@ pending_xref_error (void)
tree
lookup_name (tree name)
{
- tree decl = IDENTIFIER_SYMBOL_VALUE (name);
- if (decl == 0 || decl == error_mark_node)
- return decl;
- if (C_DECL_INVISIBLE (decl))
- return 0;
- return decl;
+ struct c_binding *b = I_SYMBOL_BINDING (name);
+ if (b && !b->invisible)
+ return b->decl;
+ return 0;
}
-/* Similar to `lookup_name' but look only at the current scope. */
+/* Similar to `lookup_name' but look only at the indicated scope. */
static tree
-lookup_name_current_level (tree name)
+lookup_name_in_scope (tree name, struct c_scope *scope)
{
- tree decl = IDENTIFIER_SYMBOL_VALUE (name);
-
- if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl))
- return 0;
-
- if (current_scope == global_scope)
- return decl;
-
- /* Scan the current scope for a decl with name NAME.
- For PARM_DECLs, we have to look at both ->parms and ->names, since
- forward parameter declarations wind up on the ->names list. */
- if (TREE_CODE (decl) == PARM_DECL
- && chain_member (decl, current_scope->parms))
- return decl;
- if (chain_member (decl, current_scope->names))
- return decl;
+ struct c_binding *b;
+ for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed)
+ if (B_IN_SCOPE (b, scope))
+ return b->decl;
return 0;
}
@@ -2212,29 +2714,30 @@ lookup_name_current_level (tree name)
void
c_init_decl_processing (void)
{
- tree endlink;
- tree ptr_ftype_void, ptr_ftype_ptr;
location_t save_loc = input_location;
- /* Adds some ggc roots, and reserved words for c-parse.in. */
+ /* Initialize reserved words for parser. */
c_parse_init ();
current_function_decl = 0;
- /* Make the c_scope structure for global names. */
- pushlevel (0);
- global_scope = current_scope;
+ gcc_obstack_init (&parser_obstack);
+
+ /* Make the externals scope. */
+ push_scope ();
+ external_scope = current_scope;
/* Declarations from c_common_nodes_and_builtins must not be associated
with this input file, lest we get differences between using and not
using preprocessed headers. */
- input_location.file = "<internal>";
+#ifdef USE_MAPPED_LOCATION
+ input_location = BUILTINS_LOCATION;
+#else
+ input_location.file = "<built-in>";
input_location.line = 0;
+#endif
- /* Make the DECL for the toplevel file scope. */
- current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
-
- build_common_tree_nodes (flag_signed_char);
+ build_common_tree_nodes (flag_signed_char, false);
c_common_nodes_and_builtins ();
@@ -2247,21 +2750,12 @@ c_init_decl_processing (void)
pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
boolean_type_node));
- endlink = void_list_node;
- ptr_ftype_void = build_function_type (ptr_type_node, endlink);
- ptr_ftype_ptr
- = build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node, endlink));
-
input_location = save_loc;
- pedantic_lvalues = pedantic;
+ pedantic_lvalues = true;
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
-
- first_builtin_decl = global_scope->names;
- last_builtin_decl = global_scope->names_last;
}
/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
@@ -2278,9 +2772,9 @@ c_make_fname_decl (tree id, int type_dep)
tree decl, type, init;
size_t length = strlen (name);
- type = build_array_type
- (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
- build_index_type (size_int (length)));
+ type = build_array_type (char_type_node,
+ build_index_type (size_int (length)));
+ type = c_build_qualified_type (type, TYPE_QUAL_CONST);
decl = build_decl (VAR_DECL, id, type);
@@ -2289,16 +2783,26 @@ c_make_fname_decl (tree id, int type_dep)
DECL_ARTIFICIAL (decl) = 1;
init = build_string (length + 1, name);
+ free ((char *) name);
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
- if (current_function_decl)
+ if (current_function_decl
+ /* For invalid programs like this:
+
+ void foo()
+ const char* p = __FUNCTION__;
+
+ the __FUNCTION__ is believed to appear in K&R style function
+ parameter declarator. In that case we still don't have
+ function_scope. */
+ && (!errorcount || current_function_scope))
{
DECL_CONTEXT (decl) = current_function_decl;
- IDENTIFIER_SYMBOL_VALUE (id) = decl;
- SCOPE_LIST_APPEND (current_function_scope, names, decl);
+ bind (id, decl, current_function_scope,
+ /*invisible=*/false, /*nested=*/false);
}
finish_decl (decl, init, NULL_TREE);
@@ -2317,23 +2821,32 @@ c_make_fname_decl (tree id, int type_dep)
tree
builtin_function (const char *name, tree type, int function_code,
- enum built_in_class class, const char *library_name,
+ enum built_in_class cl, const char *library_name,
tree attrs)
{
- tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
- DECL_EXTERNAL (decl) = 1;
+ tree id = get_identifier (name);
+ tree decl = build_decl (FUNCTION_DECL, id, type);
TREE_PUBLIC (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
+ DECL_BUILT_IN_CLASS (decl) = cl;
+ DECL_FUNCTION_CODE (decl) = function_code;
+ C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
- make_decl_rtl (decl, NULL);
- pushdecl (decl);
- DECL_BUILT_IN_CLASS (decl) = class;
- DECL_FUNCTION_CODE (decl) = function_code;
- /* Warn if a function in the namespace for users
- is used without an occasion to consider it declared. */
- if (name[0] != '_' || name[1] != '_')
- C_DECL_INVISIBLE (decl) = 1;
+ /* Should never be called on a symbol with a preexisting meaning. */
+ gcc_assert (!I_SYMBOL_BINDING (id));
+
+ bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false);
+
+ /* Builtins in the implementation namespace are made visible without
+ needing to be explicitly declared. See push_file_scope. */
+ if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
+ {
+ TREE_CHAIN (decl) = visible_builtins;
+ visible_builtins = decl;
+ }
/* Possibly apply some default attributes to this built-in function. */
if (attrs)
@@ -2353,31 +2866,21 @@ builtin_function (const char *name, tree type, int function_code,
Otherwise, it is an error. */
void
-shadow_tag (tree declspecs)
+shadow_tag (const struct c_declspecs *declspecs)
{
shadow_tag_warned (declspecs, 0);
}
+/* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning,
+ but no pedwarn. */
void
-shadow_tag_warned (tree declspecs, int warned)
-
-
- /* 1 => we have done a pedwarn. 2 => we have done a warning, but
- no pedwarn. */
+shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
{
- int found_tag = 0;
- tree link;
- tree specs, attrs;
+ bool found_tag = false;
- pending_invalid_xref = 0;
-
- /* Remove the attributes from declspecs, since they will confuse the
- following code. */
- split_specs_attrs (declspecs, &specs, &attrs);
-
- for (link = specs; link; link = TREE_CHAIN (link))
+ if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p)
{
- tree value = TREE_VALUE (link);
+ tree value = declspecs->type;
enum tree_code code = TREE_CODE (value);
if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
@@ -2387,7 +2890,7 @@ shadow_tag_warned (tree declspecs, int warned)
tree name = TYPE_NAME (value);
tree t;
- found_tag++;
+ found_tag = true;
if (name == 0)
{
@@ -2398,8 +2901,29 @@ shadow_tag_warned (tree declspecs, int warned)
warned = 1;
}
}
+ else if (!declspecs->tag_defined_p
+ && declspecs->storage_class != csc_none)
+ {
+ if (warned != 1)
+ pedwarn ("empty declaration with storage class specifier "
+ "does not redeclare tag");
+ warned = 1;
+ pending_xref_error ();
+ }
+ else if (!declspecs->tag_defined_p
+ && (declspecs->const_p
+ || declspecs->volatile_p
+ || declspecs->restrict_p))
+ {
+ if (warned != 1)
+ pedwarn ("empty declaration with type qualifier "
+ "does not redeclare tag");
+ warned = 1;
+ pending_xref_error ();
+ }
else
{
+ pending_invalid_xref = 0;
t = lookup_tag (code, name, 1);
if (t == 0)
@@ -2411,102 +2935,210 @@ shadow_tag_warned (tree declspecs, int warned)
}
else
{
- if (!warned && ! in_system_header)
+ if (warned != 1 && !in_system_header)
{
- warning ("useless keyword or type name in empty declaration");
- warned = 2;
+ pedwarn ("useless type name in empty declaration");
+ warned = 1;
}
}
}
+ else if (warned != 1 && !in_system_header && declspecs->typedef_p)
+ {
+ pedwarn ("useless type name in empty declaration");
+ warned = 1;
+ }
- if (found_tag > 1)
- error ("two types specified in one empty declaration");
+ pending_invalid_xref = 0;
+
+ if (declspecs->inline_p)
+ {
+ error ("%<inline%> in empty declaration");
+ warned = 1;
+ }
+
+ if (current_scope == file_scope && declspecs->storage_class == csc_auto)
+ {
+ error ("%<auto%> in file-scope empty declaration");
+ warned = 1;
+ }
+
+ if (current_scope == file_scope && declspecs->storage_class == csc_register)
+ {
+ error ("%<register%> in file-scope empty declaration");
+ warned = 1;
+ }
+
+ if (!warned && !in_system_header && declspecs->storage_class != csc_none)
+ {
+ warning (0, "useless storage class specifier in empty declaration");
+ warned = 2;
+ }
+
+ if (!warned && !in_system_header && declspecs->thread_p)
+ {
+ warning (0, "useless %<__thread%> in empty declaration");
+ warned = 2;
+ }
+
+ if (!warned && !in_system_header && (declspecs->const_p
+ || declspecs->volatile_p
+ || declspecs->restrict_p))
+ {
+ warning (0, "useless type qualifier in empty declaration");
+ warned = 2;
+ }
if (warned != 1)
{
- if (found_tag == 0)
+ if (!found_tag)
pedwarn ("empty declaration");
}
}
-/* Construct an array declarator. EXPR is the expression inside [], or
- NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied
- to the pointer to which a parameter array is converted). STATIC_P is
- nonzero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P
- is nonzero is the array is [*], a VLA of unspecified length which is
- nevertheless a complete type (not currently implemented by GCC),
- zero otherwise. The declarator is constructed as an ARRAY_REF
- (to be decoded by grokdeclarator), whose operand 0 is what's on the
- left of the [] (filled by in set_array_declarator_type) and operand 1
- is the expression inside; whose TREE_TYPE is the type qualifiers and
- which has TREE_STATIC set if "static" is used. */
-tree
-build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p)
+/* Return the qualifiers from SPECS as a bitwise OR of TYPE_QUAL_*
+ bits. SPECS represents declaration specifiers that the grammar
+ only permits to contain type qualifiers and attributes. */
+
+int
+quals_from_declspecs (const struct c_declspecs *specs)
{
- tree decl;
- decl = build_nt (ARRAY_REF, NULL_TREE, expr);
- TREE_TYPE (decl) = quals;
- TREE_STATIC (decl) = (static_p ? 1 : 0);
+ int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
+ | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
+ | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
+ gcc_assert (!specs->type
+ && !specs->decl_attr
+ && specs->typespec_word == cts_none
+ && specs->storage_class == csc_none
+ && !specs->typedef_p
+ && !specs->explicit_signed_p
+ && !specs->deprecated_p
+ && !specs->long_p
+ && !specs->long_long_p
+ && !specs->short_p
+ && !specs->signed_p
+ && !specs->unsigned_p
+ && !specs->complex_p
+ && !specs->inline_p
+ && !specs->thread_p);
+ return quals;
+}
+
+/* Construct an array declarator. EXPR is the expression inside [],
+ or NULL_TREE. QUALS are the type qualifiers inside the [] (to be
+ applied to the pointer to which a parameter array is converted).
+ STATIC_P is true if "static" is inside the [], false otherwise.
+ VLA_UNSPEC_P is true if the array is [*], a VLA of unspecified
+ length which is nevertheless a complete type, false otherwise. The
+ field for the contained declarator is left to be filled in by
+ set_array_declarator_inner. */
+
+struct c_declarator *
+build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p,
+ bool vla_unspec_p)
+{
+ struct c_declarator *declarator = XOBNEW (&parser_obstack,
+ struct c_declarator);
+ declarator->kind = cdk_array;
+ declarator->declarator = 0;
+ declarator->u.array.dimen = expr;
+ if (quals)
+ {
+ declarator->u.array.attrs = quals->attrs;
+ declarator->u.array.quals = quals_from_declspecs (quals);
+ }
+ else
+ {
+ declarator->u.array.attrs = NULL_TREE;
+ declarator->u.array.quals = 0;
+ }
+ declarator->u.array.static_p = static_p;
+ declarator->u.array.vla_unspec_p = vla_unspec_p;
if (pedantic && !flag_isoc99)
{
- if (static_p || quals != NULL_TREE)
- pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators");
+ if (static_p || quals != NULL)
+ pedwarn ("ISO C90 does not support %<static%> or type "
+ "qualifiers in parameter array declarators");
if (vla_unspec_p)
- pedwarn ("ISO C90 does not support `[*]' array declarators");
+ pedwarn ("ISO C90 does not support %<[*]%> array declarators");
}
if (vla_unspec_p)
- warning ("GCC does not yet properly implement `[*]' array declarators");
- return decl;
+ {
+ if (!current_scope->parm_flag)
+ {
+ /* C99 6.7.5.2p4 */
+ error ("%<[*]%> not allowed in other than function prototype scope");
+ declarator->u.array.vla_unspec_p = false;
+ return NULL;
+ }
+ current_scope->had_vla_unspec = true;
+ }
+ return declarator;
}
-/* Set the type of an array declarator. DECL is the declarator, as
- constructed by build_array_declarator; TYPE is what appears on the left
- of the [] and goes in operand 0. ABSTRACT_P is nonzero if it is an
- abstract declarator, zero otherwise; this is used to reject static and
- type qualifiers in abstract declarators, where they are not in the
- C99 grammar. */
+/* Set the contained declarator of an array declarator. DECL is the
+ declarator, as constructed by build_array_declarator; INNER is what
+ appears on the left of the []. ABSTRACT_P is true if it is an
+ abstract declarator, false otherwise; this is used to reject static
+ and type qualifiers in abstract declarators, where they are not in
+ the C99 grammar (subject to possible change in DR#289). */
-tree
-set_array_declarator_type (tree decl, tree type, int abstract_p)
+struct c_declarator *
+set_array_declarator_inner (struct c_declarator *decl,
+ struct c_declarator *inner, bool abstract_p)
{
- TREE_OPERAND (decl, 0) = type;
- if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+ decl->declarator = inner;
+ if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED
+ || decl->u.array.attrs != NULL_TREE
+ || decl->u.array.static_p))
error ("static or type qualifiers in abstract declarator");
return decl;
}
+
+/* INIT is a constructor that forms DECL's initializer. If the final
+ element initializes a flexible array field, add the size of that
+ initializer to DECL's size. */
+
+static void
+add_flexible_array_elts_to_size (tree decl, tree init)
+{
+ tree elt, type;
+
+ if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init)))
+ return;
+
+ elt = VEC_last (constructor_elt, CONSTRUCTOR_ELTS (init))->value;
+ type = TREE_TYPE (elt);
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_SIZE (type) == NULL_TREE
+ && TYPE_DOMAIN (type) != NULL_TREE
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
+ {
+ complete_array_type (&type, elt, false);
+ DECL_SIZE (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
+ }
+}
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
-groktypename (tree typename)
+groktypename (struct c_type_name *type_name)
{
- tree specs, attrs;
-
- if (TREE_CODE (typename) != TREE_LIST)
- return typename;
+ tree type;
+ tree attrs = type_name->specs->attrs;
- split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+ type_name->specs->attrs = NULL_TREE;
- typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0,
- NULL);
+ type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
+ false, NULL);
/* Apply attributes. */
- decl_attributes (&typename, attrs, 0);
+ decl_attributes (&type, attrs, 0);
- return typename;
-}
-
-/* Return a PARM_DECL node for a given pair of specs and declarator. */
-
-tree
-groktypename_in_parm_context (tree typename)
-{
- if (TREE_CODE (typename) != TREE_LIST)
- return typename;
- return grokdeclarator (TREE_VALUE (typename),
- TREE_PURPOSE (typename),
- PARM, 0, NULL);
+ return type;
}
/* Decode a declarator in an ordinary declaration or data definition.
@@ -2525,7 +3157,8 @@ groktypename_in_parm_context (tree typename)
grokfield and not through here. */
tree
-start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
+start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
+ bool initialized, tree attributes)
{
tree decl;
tree tem;
@@ -2537,44 +3170,43 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
decl = grokdeclarator (declarator, declspecs,
NORMAL, initialized, NULL);
+ if (!decl)
+ return 0;
deprecated_state = DEPRECATED_NORMAL;
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& MAIN_NAME_P (DECL_NAME (decl)))
- warning ("%J'%D' is usually a function", decl, decl);
+ warning (OPT_Wmain, "%q+D is usually a function", decl);
if (initialized)
/* Is it valid for this decl to have an initializer at all?
If not, set INITIALIZED to zero, which will indirectly
- tell `finish_decl' to ignore the initializer once it is parsed. */
+ tell 'finish_decl' to ignore the initializer once it is parsed. */
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- error ("typedef `%s' is initialized (use __typeof__ instead)",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("typedef %qD is initialized (use __typeof__ instead)", decl);
initialized = 0;
break;
case FUNCTION_DECL:
- error ("function `%s' is initialized like a variable",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("function %qD is initialized like a variable", decl);
initialized = 0;
break;
case PARM_DECL:
/* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE. */
- error ("parameter `%s' is initialized",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("parameter %qD is initialized", decl);
initialized = 0;
break;
default:
- /* Don't allow initializations for incomplete types
- except for arrays which might be completed by the initialization. */
+ /* Don't allow initializations for incomplete types except for
+ arrays which might be completed by the initialization. */
- /* This can happen if the array size is an undefined macro. We already
- gave a warning, so we don't need another one. */
+ /* This can happen if the array size is an undefined macro.
+ We already gave a warning, so we don't need another one. */
if (TREE_TYPE (decl) == error_mark_node)
initialized = 0;
else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
@@ -2590,27 +3222,28 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
}
else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
{
- error ("variable `%s' has initializer but incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("variable %qD has initializer but incomplete type", decl);
initialized = 0;
}
- else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
+ else if (C_DECL_VARIABLE_SIZE (decl))
{
- error ("elements of array `%s' have incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ /* Although C99 is unclear about whether incomplete arrays
+ of VLAs themselves count as VLAs, it does not make
+ sense to permit them to be initialized given that
+ ordinary VLAs may not be initialized. */
+ error ("variable-sized object may not be initialized");
initialized = 0;
}
}
if (initialized)
{
- DECL_EXTERNAL (decl) = 0;
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
TREE_STATIC (decl) = 1;
- /* Tell `pushdecl' this is an initialized decl
+ /* Tell 'pushdecl' this is an initialized decl
even though we don't yet have the initializer expression.
- Also tell `finish_decl' it may store the real initializer. */
+ Also tell 'finish_decl' it may store the real initializer. */
DECL_INITIAL (decl) = error_mark_node;
}
@@ -2634,7 +3267,7 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
if (TREE_CODE (decl) == VAR_DECL
&& !initialized
&& TREE_PUBLIC (decl)
- && !DECL_THREAD_LOCAL (decl)
+ && !DECL_THREAD_LOCAL_P (decl)
&& !flag_no_common)
DECL_COMMON (decl) = 1;
@@ -2644,17 +3277,17 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
if (TREE_CODE (decl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (decl)))
{
- tree ce = declarator;
+ struct c_declarator *ce = declarator;
- if (TREE_CODE (ce) == INDIRECT_REF)
- ce = TREE_OPERAND (declarator, 0);
- if (TREE_CODE (ce) == CALL_EXPR)
+ if (ce->kind == cdk_pointer)
+ ce = declarator->declarator;
+ if (ce->kind == cdk_function)
{
- tree args = TREE_PURPOSE (TREE_OPERAND (ce, 1));
+ tree args = ce->u.arg_info->parms;
for (; args; args = TREE_CHAIN (args))
{
tree type = TREE_TYPE (args);
- if (INTEGRAL_TYPE_P (type)
+ if (type && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (args) = integer_type_node;
}
@@ -2665,30 +3298,39 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
- warning ("%Jinline function '%D' given attribute noinline", decl, decl);
+ warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
+ decl);
/* Add this decl to the current scope.
TEM may equal DECL or it may be a previous decl of the same name. */
tem = pushdecl (decl);
- /* For a local variable, define the RTL now. */
- if (current_scope != global_scope
- /* But not if this is a duplicate decl
- and we preserved the rtl from the previous one
- (which may or may not happen). */
- && !DECL_RTL_SET_P (tem)
- && DECL_FILE_SCOPE_P (tem))
+ if (initialized && DECL_EXTERNAL (tem))
{
- if (TREE_TYPE (tem) != error_mark_node
- && (COMPLETE_TYPE_P (TREE_TYPE (tem))
- || (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
- && DECL_INITIAL (tem) != 0)))
- expand_decl (tem);
+ DECL_EXTERNAL (tem) = 0;
+ TREE_STATIC (tem) = 1;
}
return tem;
}
+/* Initialize EH if not initialized yet and exceptions are enabled. */
+
+void
+c_maybe_initialize_eh (void)
+{
+ if (!flag_exceptions || c_eh_initialized_p)
+ return;
+
+ c_eh_initialized_p = true;
+ eh_personality_libfunc
+ = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+ ? "__gcc_personality_sj0"
+ : "__gcc_personality_v0");
+ default_init_unwind_resume_libfunc ();
+ using_eh_for_cleanups ();
+}
+
/* Finish processing of a declaration;
install its initial value.
If the length of an array type is not known before,
@@ -2697,12 +3339,13 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
void
finish_decl (tree decl, tree init, tree asmspec_tree)
{
- tree type = TREE_TYPE (decl);
+ tree type;
int was_incomplete = (DECL_SIZE (decl) == 0);
const char *asmspec = 0;
/* If a name was specified, get the string. */
- if (current_scope == global_scope)
+ if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
+ && DECL_FILE_SCOPE_P (decl))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -2719,56 +3362,86 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
store_init_value (decl, init);
if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == FIELD_DECL))
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == FIELD_DECL))
objc_check_decl (decl);
+ type = TREE_TYPE (decl);
+
/* Deduce size of array from initialization, if not already known. */
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == 0
&& TREE_CODE (decl) != TYPE_DECL)
{
- int do_default
+ bool do_default
= (TREE_STATIC (decl)
/* Even if pedantic, an external linkage array
may have incomplete type at first. */
? pedantic && !TREE_PUBLIC (decl)
: !DECL_EXTERNAL (decl));
int failure
- = complete_array_type (type, DECL_INITIAL (decl), do_default);
+ = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl),
+ do_default);
/* Get the completed type made by complete_array_type. */
type = TREE_TYPE (decl);
- if (failure == 1)
- error ("%Jinitializer fails to determine size of '%D'", decl, decl);
-
- else if (failure == 2)
+ switch (failure)
{
+ case 1:
+ error ("initializer fails to determine size of %q+D", decl);
+ break;
+
+ case 2:
if (do_default)
- error ("%Jarray size missing in '%D'", decl, decl);
+ error ("array size missing in %q+D", decl);
/* If a `static' var's size isn't known,
make it extern as well as static, so it does not get
allocated.
If it is not `static', then do not mark extern;
finish_incomplete_decl will give it a default size
and it will get allocated. */
- else if (!pedantic && TREE_STATIC (decl) && ! TREE_PUBLIC (decl))
+ else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
DECL_EXTERNAL (decl) = 1;
+ break;
+
+ case 3:
+ error ("zero or negative size array %q+D", decl);
+ break;
+
+ case 0:
+ /* For global variables, update the copy of the type that
+ exists in the binding. */
+ if (TREE_PUBLIC (decl))
+ {
+ struct c_binding *b_ext = I_SYMBOL_BINDING (DECL_NAME (decl));
+ while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
+ b_ext = b_ext->shadowed;
+ if (b_ext)
+ {
+ if (b_ext->type)
+ b_ext->type = composite_type (b_ext->type, type);
+ else
+ b_ext->type = type;
+ }
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
}
- /* TYPE_MAX_VALUE is always one less than the number of elements
- in the array, because we start counting at zero. Therefore,
- warn only if the value is less than zero. */
- else if (pedantic && TYPE_DOMAIN (type) != 0
- && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
- error ("%Jzero or negative size array '%D'", decl, decl);
+ if (DECL_INITIAL (decl))
+ TREE_TYPE (DECL_INITIAL (decl)) = type;
layout_decl (decl, 0);
}
if (TREE_CODE (decl) == VAR_DECL)
{
+ if (init && TREE_CODE (init) == CONSTRUCTOR)
+ add_flexible_array_elts_to_size (decl, init);
+
if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node
&& COMPLETE_TYPE_P (TREE_TYPE (decl)))
layout_decl (decl, 0);
@@ -2777,22 +3450,20 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
/* Don't give an error if we already gave one earlier. */
&& TREE_TYPE (decl) != error_mark_node
&& (TREE_STATIC (decl)
- ?
- /* A static variable with an incomplete type
- is an error if it is initialized.
- Also if it is not file scope.
- Otherwise, let it through, but if it is not `extern'
- then it may cause an error message later. */
- (DECL_INITIAL (decl) != 0
+ /* A static variable with an incomplete type
+ is an error if it is initialized.
+ Also if it is not file scope.
+ Otherwise, let it through, but if it is not `extern'
+ then it may cause an error message later. */
+ ? (DECL_INITIAL (decl) != 0
|| !DECL_FILE_SCOPE_P (decl))
- :
- /* An automatic variable with an incomplete type
- is an error. */
- !DECL_EXTERNAL (decl)))
- {
- error ("%Jstorage size of '%D' isn't known", decl, decl);
- TREE_TYPE (decl) = error_mark_node;
- }
+ /* An automatic variable with an incomplete type
+ is an error. */
+ : !DECL_EXTERNAL (decl)))
+ {
+ error ("storage size of %q+D isn%'t known", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
&& DECL_SIZE (decl) != 0)
@@ -2800,7 +3471,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
- error ("%Jstorage size of '%D' isn't constant", decl, decl);
+ error ("storage size of %q+D isn%'t constant", decl);
}
if (TREE_USED (type))
@@ -2812,36 +3483,13 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
was a normal built-in. */
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
{
- /* ASMSPEC is given, and not the name of a register. Mark the
- name with a star so assemble_name won't munge it. */
- char *starred = alloca (strlen (asmspec) + 2);
- starred[0] = '*';
- strcpy (starred + 1, asmspec);
-
if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
- {
- tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
- SET_DECL_RTL (builtin, NULL_RTX);
- SET_DECL_ASSEMBLER_NAME (builtin, get_identifier (starred));
-#ifdef TARGET_MEM_FUNCTIONS
- if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
- init_block_move_fn (starred);
- else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
- init_block_clear_fn (starred);
-#else
- if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BCOPY)
- init_block_move_fn (starred);
- else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BZERO)
- init_block_clear_fn (starred);
-#endif
- }
- SET_DECL_RTL (decl, NULL_RTX);
- change_decl_assembler_name (decl, get_identifier (starred));
+ set_builtin_user_assembler_name (decl, asmspec);
+ set_user_assembler_name (decl, asmspec);
}
/* If #pragma weak was used, mark the decl weak now. */
- if (current_scope == global_scope)
- maybe_apply_pragma_weak (decl);
+ maybe_apply_pragma_weak (decl);
/* Output the assembler code and/or RTL code for variables and functions,
unless the type is an undefined structure or union.
@@ -2849,10 +3497,31 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
+ /* Determine the ELF visibility. */
+ if (TREE_PUBLIC (decl))
+ c_determine_visibility (decl);
+
/* This is a no-op in c-lang.c or something real in objc-act.c. */
if (c_dialect_objc ())
objc_check_decl (decl);
+ if (asmspec)
+ {
+ /* If this is not a static variable, issue a warning.
+ It doesn't make any sense to give an ASMSPEC for an
+ ordinary, non-register local variable. Historically,
+ GCC has accepted -- but ignored -- the ASMSPEC in
+ this case. */
+ if (!DECL_FILE_SCOPE_P (decl)
+ && TREE_CODE (decl) == VAR_DECL
+ && !C_DECL_REGISTER (decl)
+ && !TREE_STATIC (decl))
+ warning (0, "ignoring asm-specifier for non-static local "
+ "variable %q+D", decl);
+ else
+ set_user_assembler_name (decl, asmspec);
+ }
+
if (DECL_FILE_SCOPE_P (decl))
{
if (DECL_INITIAL (decl) == NULL_TREE
@@ -2861,44 +3530,51 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
when a tentative file-scope definition is seen.
But at end of compilation, do output code for them. */
DECL_DEFER_OUTPUT (decl) = 1;
- rest_of_decl_compilation (decl, asmspec, true, 0);
+ rest_of_decl_compilation (decl, true, 0);
}
else
{
- /* This is a local variable. If there is an ASMSPEC, the
- user has requested that we handle it specially. */
- if (asmspec)
+ /* In conjunction with an ASMSPEC, the `register'
+ keyword indicates that we should place the variable
+ in a particular register. */
+ if (asmspec && C_DECL_REGISTER (decl))
{
- /* In conjunction with an ASMSPEC, the `register'
- keyword indicates that we should place the variable
- in a particular register. */
- if (DECL_REGISTER (decl))
- DECL_C_HARD_REGISTER (decl) = 1;
-
- /* If this is not a static variable, issue a warning.
- It doesn't make any sense to give an ASMSPEC for an
- ordinary, non-register local variable. Historically,
- GCC has accepted -- but ignored -- the ASMSPEC in
- this case. */
- if (TREE_CODE (decl) == VAR_DECL
- && !DECL_REGISTER (decl)
- && !TREE_STATIC (decl))
- warning ("%Jignoring asm-specifier for non-static local "
- "variable '%D'", decl, decl);
- else
- change_decl_assembler_name (decl, get_identifier (asmspec));
+ DECL_HARD_REGISTER (decl) = 1;
+ /* This cannot be done for a structure with volatile
+ fields, on which DECL_REGISTER will have been
+ reset. */
+ if (!DECL_REGISTER (decl))
+ error ("cannot put object with volatile field into register");
}
if (TREE_CODE (decl) != FUNCTION_DECL)
- add_decl_stmt (decl);
+ {
+ /* If we're building a variable sized type, and we might be
+ reachable other than via the top of the current binding
+ level, then create a new BIND_EXPR so that we deallocate
+ the object at the right time. */
+ /* Note that DECL_SIZE can be null due to errors. */
+ if (DECL_SIZE (decl)
+ && !TREE_CONSTANT (DECL_SIZE (decl))
+ && STATEMENT_LIST_HAS_LABEL (cur_stmt_list))
+ {
+ tree bind;
+ bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ add_stmt (bind);
+ BIND_EXPR_BODY (bind) = push_stmt_list ();
+ }
+ add_stmt (build_stmt (DECL_EXPR, decl));
+ }
}
+
if (!DECL_FILE_SCOPE_P (decl))
{
/* Recompute the RTL of a local array now
if it used to be an incomplete type. */
if (was_incomplete
- && ! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl))
+ && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
{
/* If we used it already as memory, it must stay in memory. */
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
@@ -2910,16 +3586,22 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
}
/* If this was marked 'used', be sure it will be output. */
- if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- mark_referenced (DECL_ASSEMBLER_NAME (decl));
+ if (!flag_unit_at_a_time && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+ mark_decl_referenced (decl);
if (TREE_CODE (decl) == TYPE_DECL)
- rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
+ {
+ if (!DECL_FILE_SCOPE_P (decl)
+ && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+ add_stmt (build_stmt (DECL_EXPR, decl));
+
+ rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0);
+ }
/* At the end of a declaration, throw away any variable type sizes
of types defined inside that declaration. There is no use
computing them in the following function definition. */
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
get_pending_sizes ();
/* Install a cleanup (aka destructor) if one was given. */
@@ -2928,8 +3610,6 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
if (attr)
{
- static bool eh_initialized_p;
-
tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
tree cleanup_decl = lookup_name (cleanup_id);
tree cleanup;
@@ -2941,67 +3621,52 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
+ TREE_USED (cleanup_decl) = 1;
/* Initialize EH, if we've been told to do so. */
- if (flag_exceptions && !eh_initialized_p)
- {
- eh_initialized_p = true;
- eh_personality_libfunc
- = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- ? "__gcc_personality_sj0"
- : "__gcc_personality_v0");
- using_eh_for_cleanups ();
- }
+ c_maybe_initialize_eh ();
- add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+ push_cleanup (decl, cleanup, false);
}
}
}
+/* Given a parsed parameter declaration, decode it into a PARM_DECL. */
+
+tree
+grokparm (const struct c_parm *parm)
+{
+ tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
+ NULL);
+
+ decl_attributes (&decl, parm->attrs, 0);
+
+ return decl;
+}
+
/* Given a parsed parameter declaration, decode it into a PARM_DECL
and push that on the current scope. */
void
-push_parm_decl (tree parm)
+push_parm_decl (const struct c_parm *parm)
{
tree decl;
- int old_dont_save_pending_sizes_p = 0;
- /* Don't attempt to expand sizes while parsing this decl.
- (We can get here with i_s_e 1 somehow from Objective-C.) */
- int save_immediate_size_expand = immediate_size_expand;
- immediate_size_expand = 0;
-
- /* If this is a nested function, we do want to keep SAVE_EXPRs for
- the argument sizes, regardless of the parent's setting. */
- if (cfun)
- {
- old_dont_save_pending_sizes_p = cfun->x_dont_save_pending_sizes_p;
- cfun->x_dont_save_pending_sizes_p = 0;
- }
-
- decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
- TREE_PURPOSE (TREE_PURPOSE (parm)),
- PARM, 0, NULL);
- decl_attributes (&decl, TREE_VALUE (parm), 0);
+ decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
+ decl_attributes (&decl, parm->attrs, 0);
decl = pushdecl (decl);
finish_decl (decl, NULL_TREE, NULL_TREE);
-
- if (cfun)
- cfun->x_dont_save_pending_sizes_p = old_dont_save_pending_sizes_p;
- immediate_size_expand = save_immediate_size_expand;
}
-/* Mark all the parameter declarations to date as forward decls,
- shift them to the variables list, and reset the parameters list.
+/* Mark all the parameter declarations to date as forward decls.
Also diagnose use of this extension. */
void
mark_forward_parm_decls (void)
{
- tree parm;
+ struct c_binding *b;
if (pedantic && !current_scope->warned_forward_parm_decls)
{
@@ -3009,16 +3674,11 @@ mark_forward_parm_decls (void)
current_scope->warned_forward_parm_decls = true;
}
- for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
- TREE_ASM_WRITTEN (parm) = 1;
-
- SCOPE_LIST_CONCAT (current_scope, names, current_scope, parms);
- current_scope->parms = 0;
- current_scope->parms_last = 0;
+ for (b = current_scope->bindings; b; b = b->prev)
+ if (TREE_CODE (b->decl) == PARM_DECL)
+ TREE_ASM_WRITTEN (b->decl) = 1;
}
-static GTY(()) int compound_literal_number;
-
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR that initializes the compound
@@ -3029,123 +3689,58 @@ build_compound_literal (tree type, tree init)
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
- the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT. */
- tree decl = build_decl (VAR_DECL, NULL_TREE, type);
+ the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR. */
+ tree decl;
tree complit;
tree stmt;
+
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ decl = build_decl (VAR_DECL, NULL_TREE, type);
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
- TREE_STATIC (decl) = (current_scope == global_scope);
+ TREE_STATIC (decl) = (current_scope == file_scope);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
TREE_TYPE (decl) = type;
- TREE_READONLY (decl) = TREE_READONLY (type);
+ TREE_READONLY (decl) = TYPE_READONLY (type);
store_init_value (decl, init);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
- int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
- if (failure)
- abort ();
+ int failure = complete_array_type (&TREE_TYPE (decl),
+ DECL_INITIAL (decl), true);
+ gcc_assert (!failure);
+
+ type = TREE_TYPE (decl);
+ TREE_TYPE (DECL_INITIAL (decl)) = type;
}
- type = TREE_TYPE (decl);
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
return error_mark_node;
- stmt = build_stmt (DECL_STMT, decl);
- complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
+ stmt = build_stmt (DECL_EXPR, decl);
+ complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt);
TREE_SIDE_EFFECTS (complit) = 1;
layout_decl (decl, 0);
if (TREE_STATIC (decl))
{
- /* This decl needs a name for the assembler output. We also need
- a unique suffix to be added to the name. */
- char *name;
-
- ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
- compound_literal_number);
- compound_literal_number++;
- DECL_NAME (decl) = get_identifier (name);
+ /* This decl needs a name for the assembler output. */
+ set_compound_literal_name (decl);
DECL_DEFER_OUTPUT (decl) = 1;
DECL_COMDAT (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
pushdecl (decl);
- rest_of_decl_compilation (decl, NULL, 1, 0);
+ rest_of_decl_compilation (decl, 1, 0);
}
return complit;
}
-/* Make TYPE a complete type based on INITIAL_VALUE.
- Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
- 2 if there was no information (in which case assume 1 if DO_DEFAULT). */
-
-int
-complete_array_type (tree type, tree initial_value, int do_default)
-{
- tree maxindex = NULL_TREE;
- int value = 0;
-
- if (initial_value)
- {
- /* Note MAXINDEX is really the maximum index,
- one less than the size. */
- if (TREE_CODE (initial_value) == STRING_CST)
- {
- int eltsize
- = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
- maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
- / eltsize) - 1, 0);
- }
- else if (TREE_CODE (initial_value) == CONSTRUCTOR)
- {
- tree elts = CONSTRUCTOR_ELTS (initial_value);
- maxindex = build_int_2 (-1, -1);
- for (; elts; elts = TREE_CHAIN (elts))
- {
- if (TREE_PURPOSE (elts))
- maxindex = TREE_PURPOSE (elts);
- else
- maxindex = fold (build (PLUS_EXPR, integer_type_node,
- maxindex, integer_one_node));
- }
- maxindex = copy_node (maxindex);
- }
- else
- {
- /* Make an error message unless that happened already. */
- if (initial_value != error_mark_node)
- value = 1;
-
- /* Prevent further error messages. */
- maxindex = build_int_2 (0, 0);
- }
- }
-
- if (!maxindex)
- {
- if (do_default)
- maxindex = build_int_2 (0, 0);
- value = 2;
- }
-
- if (maxindex)
- {
- TYPE_DOMAIN (type) = build_index_type (maxindex);
- if (!TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
- }
-
- /* Lay out the type now that we can get the real answer. */
-
- layout_type (type);
-
- return value;
-}
-
/* Determine whether TYPE is a structure with a flexible array member,
or a union containing such a structure (possibly recursively). */
@@ -3189,14 +3784,12 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
unsigned HOST_WIDE_INT w;
const char *name = orig_name ? orig_name: _("<anonymous>");
- /* Necessary? */
- STRIP_NOPS (*width);
-
/* Detect and ignore out of range field width and process valid
field widths. */
- if (TREE_CODE (*width) != INTEGER_CST)
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (*width))
+ || TREE_CODE (*width) != INTEGER_CST)
{
- error ("bit-field `%s' width not an integer constant", name);
+ error ("bit-field %qs width not an integer constant", name);
*width = integer_one_node;
}
else
@@ -3204,12 +3797,12 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
constant_expression_warning (*width);
if (tree_int_cst_sgn (*width) < 0)
{
- error ("negative width in bit-field `%s'", name);
+ error ("negative width in bit-field %qs", name);
*width = integer_one_node;
}
else if (integer_zerop (*width) && orig_name)
{
- error ("zero width for bit-field `%s'", name);
+ error ("zero width for bit-field %qs", name);
*width = integer_one_node;
}
}
@@ -3219,16 +3812,17 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
&& TREE_CODE (*type) != BOOLEAN_TYPE
&& TREE_CODE (*type) != ENUMERAL_TYPE)
{
- error ("bit-field `%s' has invalid type", name);
+ error ("bit-field %qs has invalid type", name);
*type = unsigned_type_node;
}
type_mv = TYPE_MAIN_VARIANT (*type);
if (pedantic
+ && !in_system_header
&& type_mv != integer_type_node
&& type_mv != unsigned_type_node
&& type_mv != boolean_type_node)
- pedwarn ("type of bit-field `%s' is a GCC extension", name);
+ pedwarn ("type of bit-field %qs is a GCC extension", name);
if (type_mv == boolean_type_node)
max_width = CHAR_TYPE_SIZE;
@@ -3237,18 +3831,23 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
if (0 < compare_tree_int (*width, max_width))
{
- error ("width of `%s' exceeds its type", name);
+ error ("width of %qs exceeds its type", name);
w = max_width;
- *width = build_int_2 (w, 0);
+ *width = build_int_cst (NULL_TREE, w);
}
else
w = tree_low_cst (*width, 1);
- if (TREE_CODE (*type) == ENUMERAL_TYPE
- && (w < min_precision (TYPE_MIN_VALUE (*type), TREE_UNSIGNED (*type))
- || w < min_precision (TYPE_MAX_VALUE (*type), TREE_UNSIGNED (*type))))
- warning ("`%s' is narrower than values of its type", name);
+ if (TREE_CODE (*type) == ENUMERAL_TYPE)
+ {
+ struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
+ if (!lt
+ || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
+ || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
+ warning (0, "%qs is narrower than values of its type", name);
+ }
}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
@@ -3256,8 +3855,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
(In one case we can return a ..._TYPE node instead.
For invalid input we sometimes return 0.)
- DECLSPECS is a chain of tree_list nodes whose value fields
- are the storage classes and type specifiers.
+ DECLSPECS is a c_declspecs structure for the declaration specifiers.
DECL_CONTEXT says which syntactic context this declaration is in:
NORMAL for most contexts. Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
@@ -3269,7 +3867,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
TYPENAME if for a typename (in a cast or sizeof).
Don't make a DECL node; just return the ..._TYPE node.
FIELD for a struct or union field; make a FIELD_DECL.
- INITIALIZED is 1 if the decl has an initializer.
+ INITIALIZED is true if the decl has an initializer.
WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
representing the width of the bit-field.
@@ -3281,64 +3879,63 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
and `extern' are interpreted. */
static tree
-grokdeclarator (tree declarator, tree declspecs,
- enum decl_context decl_context, int initialized, tree *width)
+grokdeclarator (const struct c_declarator *declarator,
+ struct c_declspecs *declspecs,
+ enum decl_context decl_context, bool initialized, tree *width)
{
- int specbits = 0;
- tree spec;
- tree type = NULL_TREE;
- int longlong = 0;
+ tree type = declspecs->type;
+ bool threadp = declspecs->thread_p;
+ enum c_storage_class storage_class = declspecs->storage_class;
int constp;
int restrictp;
int volatilep;
int type_quals = TYPE_UNQUALIFIED;
- int inlinep;
- int explicit_int = 0;
- int explicit_char = 0;
- int defaulted_int = 0;
- tree typedef_decl = 0;
const char *name, *orig_name;
tree typedef_type = 0;
- int funcdef_flag = 0;
- enum tree_code innermost_code = ERROR_MARK;
+ bool funcdef_flag = false;
+ bool funcdef_syntax = false;
int size_varies = 0;
- tree decl_attr = NULL_TREE;
- tree array_ptr_quals = NULL_TREE;
+ tree decl_attr = declspecs->decl_attr;
+ int array_ptr_quals = TYPE_UNQUALIFIED;
+ tree array_ptr_attrs = NULL_TREE;
int array_parm_static = 0;
+ bool array_parm_vla_unspec_p = false;
tree returned_attrs = NULL_TREE;
bool bitfield = width != NULL;
tree element_type;
+ struct c_arg_info *arg_info = 0;
if (decl_context == FUNCDEF)
- funcdef_flag = 1, decl_context = NORMAL;
+ funcdef_flag = true, decl_context = NORMAL;
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
- tree decl = declarator;
+ const struct c_declarator *decl = declarator;
name = 0;
while (decl)
- switch (TREE_CODE (decl))
+ switch (decl->kind)
{
- case ARRAY_REF:
- case INDIRECT_REF:
- case CALL_EXPR:
- innermost_code = TREE_CODE (decl);
- decl = TREE_OPERAND (decl, 0);
+ case cdk_function:
+ case cdk_array:
+ case cdk_pointer:
+ funcdef_syntax = (decl->kind == cdk_function);
+ decl = decl->declarator;
break;
- case TREE_LIST:
- decl = TREE_VALUE (decl);
+ case cdk_attrs:
+ decl = decl->declarator;
break;
- case IDENTIFIER_NODE:
- name = IDENTIFIER_POINTER (decl);
+ case cdk_id:
+ if (decl->u.id)
+ name = IDENTIFIER_POINTER (decl->u.id);
decl = 0;
break;
default:
- abort ();
+ gcc_unreachable ();
}
orig_name = name;
if (name == 0)
@@ -3348,302 +3945,49 @@ grokdeclarator (tree declarator, tree declspecs,
/* A function definition's declarator must have the form of
a function declarator. */
- if (funcdef_flag && innermost_code != CALL_EXPR)
+ if (funcdef_flag && !funcdef_syntax)
return 0;
/* If this looks like a function definition, make it one,
even if it occurs where parms are expected.
Then store_parm_decls will reject it and not use it as a parm. */
- if (decl_context == NORMAL && !funcdef_flag
- && current_scope->parm_flag)
+ if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
decl_context = PARM;
- /* Look through the decl specs and record which ones appear.
- Some typespecs are defined as built-in typenames.
- Others, the ones that are modifiers of other types,
- are represented by bits in SPECBITS: set the bits for
- the modifiers that appear. Storage class keywords are also in SPECBITS.
-
- If there is a typedef name or a type, store the type in TYPE.
- This includes builtin typedefs such as `int'.
-
- Set EXPLICIT_INT or EXPLICIT_CHAR if the type is `int' or `char'
- and did not come from a user typedef.
-
- Set LONGLONG if `long' is mentioned twice. */
-
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
- {
- tree id = TREE_VALUE (spec);
-
- /* If the entire declaration is itself tagged as deprecated then
- suppress reports of deprecated items. */
- if (id && TREE_DEPRECATED (id))
- {
- if (deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (id);
- }
-
- if (id == ridpointers[(int) RID_INT])
- explicit_int = 1;
- if (id == ridpointers[(int) RID_CHAR])
- explicit_char = 1;
-
- if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
- {
- enum rid i = C_RID_CODE (id);
- if ((int) i <= (int) RID_LAST_MODIFIER)
- {
- if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
- {
- if (longlong)
- error ("`long long long' is too long for GCC");
- else
- {
- if (pedantic && !flag_isoc99 && ! in_system_header
- && warn_long_long)
- pedwarn ("ISO C90 does not support `long long'");
- longlong = 1;
- }
- }
- else if (specbits & (1 << (int) i))
- {
- if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
- {
- if (pedantic && !flag_isoc99)
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
- }
- else
- error ("duplicate `%s'", IDENTIFIER_POINTER (id));
- }
-
- /* Diagnose "__thread extern". Recall that this list
- is in the reverse order seen in the text. */
- if (i == RID_THREAD
- && (specbits & (1 << (int) RID_EXTERN
- | 1 << (int) RID_STATIC)))
- {
- if (specbits & 1 << (int) RID_EXTERN)
- error ("`__thread' before `extern'");
- else
- error ("`__thread' before `static'");
- }
-
- specbits |= 1 << (int) i;
- goto found;
- }
- }
- if (type)
- error ("two or more data types in declaration of `%s'", name);
- /* Actual typedefs come to us as TYPE_DECL nodes. */
- else if (TREE_CODE (id) == TYPE_DECL)
- {
- if (TREE_TYPE (id) == error_mark_node)
- ; /* Allow the type to default to int to avoid cascading errors. */
- else
- {
- type = TREE_TYPE (id);
- decl_attr = DECL_ATTRIBUTES (id);
- typedef_decl = id;
- }
- }
- /* Built-in types come as identifiers. */
- else if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- tree t = lookup_name (id);
- if (TREE_TYPE (t) == error_mark_node)
- ;
- else if (!t || TREE_CODE (t) != TYPE_DECL)
- error ("`%s' fails to be a typedef or built in type",
- IDENTIFIER_POINTER (id));
- else
- {
- type = TREE_TYPE (t);
- typedef_decl = t;
- }
- }
- else if (TREE_CODE (id) != ERROR_MARK)
- type = id;
-
- found:
- ;
- }
-
- typedef_type = type;
- if (type)
- size_varies = C_TYPE_VARIABLE_SIZE (type);
+ if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (declspecs->type);
- /* No type at all: default to `int', and set DEFAULTED_INT
- because it was not a user-defined typedef. */
-
- if (type == 0)
+ if ((decl_context == NORMAL || decl_context == FIELD)
+ && current_scope == file_scope
+ && variably_modified_type_p (type, NULL_TREE))
{
- if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_SIGNED)
- | (1 << (int) RID_UNSIGNED)
- | (1 << (int) RID_COMPLEX))))
- /* Don't warn about typedef foo = bar. */
- && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
- && ! in_system_header)
- {
- /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type
- and this is a function, or if -Wimplicit; prefer the former
- warning since it is more explicit. */
- if ((warn_implicit_int || warn_return_type || flag_isoc99)
- && funcdef_flag)
- warn_about_return_type = 1;
- else if (warn_implicit_int || flag_isoc99)
- pedwarn_c99 ("type defaults to `int' in declaration of `%s'",
- name);
- }
-
- defaulted_int = 1;
+ error ("variably modified %qs at file scope", name);
type = integer_type_node;
}
- /* Now process the modifiers that were specified
- and check for invalid combinations. */
-
- /* Long double is a special combination. */
-
- if ((specbits & 1 << (int) RID_LONG) && ! longlong
- && TYPE_MAIN_VARIANT (type) == double_type_node)
- {
- specbits &= ~(1 << (int) RID_LONG);
- type = long_double_type_node;
- }
+ typedef_type = type;
+ size_varies = C_TYPE_VARIABLE_SIZE (type);
- /* Check all other uses of type modifiers. */
+ /* Diagnose defaulting to "int". */
- if (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED)))
+ if (declspecs->default_int_p && !in_system_header)
{
- int ok = 0;
-
- if ((specbits & 1 << (int) RID_LONG)
- && (specbits & 1 << (int) RID_SHORT))
- error ("both long and short specified for `%s'", name);
- else if (((specbits & 1 << (int) RID_LONG)
- || (specbits & 1 << (int) RID_SHORT))
- && explicit_char)
- error ("long or short specified with char for `%s'", name);
- else if (((specbits & 1 << (int) RID_LONG)
- || (specbits & 1 << (int) RID_SHORT))
- && TREE_CODE (type) == REAL_TYPE)
- {
- static int already = 0;
-
- error ("long or short specified with floating type for `%s'", name);
- if (! already && ! pedantic)
- {
- error ("the only valid combination is `long double'");
- already = 1;
- }
- }
- else if ((specbits & 1 << (int) RID_SIGNED)
- && (specbits & 1 << (int) RID_UNSIGNED))
- error ("both signed and unsigned specified for `%s'", name);
- else if (TREE_CODE (type) != INTEGER_TYPE)
- error ("long, short, signed or unsigned invalid for `%s'", name);
- else
- {
- ok = 1;
- if (!explicit_int && !defaulted_int && !explicit_char)
- {
- error ("long, short, signed or unsigned used invalidly for `%s'",
- name);
- ok = 0;
- }
- }
-
- /* Discard the type modifiers if they are invalid. */
- if (! ok)
- {
- specbits &= ~((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED));
- longlong = 0;
- }
+ /* Issue a warning if this is an ISO C 99 program or if
+ -Wreturn-type and this is a function, or if -Wimplicit;
+ prefer the former warning since it is more explicit. */
+ if ((warn_implicit_int || warn_return_type || flag_isoc99)
+ && funcdef_flag)
+ warn_about_return_type = 1;
+ else if (warn_implicit_int || flag_isoc99)
+ pedwarn_c99 ("type defaults to %<int%> in declaration of %qs", name);
}
- if ((specbits & (1 << (int) RID_COMPLEX))
- && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
- {
- error ("complex invalid for `%s'", name);
- specbits &= ~(1 << (int) RID_COMPLEX);
- }
-
- /* Decide whether an integer type is signed or not.
- Optionally treat bit-fields as signed by default. */
- if (specbits & 1 << (int) RID_UNSIGNED
- || (bitfield && ! flag_signed_bitfields
- && (explicit_int || defaulted_int || explicit_char
- /* A typedef for plain `int' without `signed'
- can be controlled just like plain `int'. */
- || ! (typedef_decl != 0
- && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
- && TREE_CODE (type) != ENUMERAL_TYPE
- && !(specbits & 1 << (int) RID_SIGNED)))
- {
- if (longlong)
- type = long_long_unsigned_type_node;
- else if (specbits & 1 << (int) RID_LONG)
- type = long_unsigned_type_node;
- else if (specbits & 1 << (int) RID_SHORT)
- type = short_unsigned_type_node;
- else if (type == char_type_node)
- type = unsigned_char_type_node;
- else if (typedef_decl)
- type = c_common_unsigned_type (type);
- else
- type = unsigned_type_node;
- }
- else if ((specbits & 1 << (int) RID_SIGNED)
- && type == char_type_node)
- type = signed_char_type_node;
- else if (longlong)
- type = long_long_integer_type_node;
- else if (specbits & 1 << (int) RID_LONG)
- type = long_integer_type_node;
- else if (specbits & 1 << (int) RID_SHORT)
- type = short_integer_type_node;
-
- if (specbits & 1 << (int) RID_COMPLEX)
- {
- if (pedantic && !flag_isoc99)
- pedwarn ("ISO C90 does not support complex types");
- /* If we just have "complex", it is equivalent to
- "complex double", but if any modifiers at all are specified it is
- the complex form of TYPE. E.g, "complex short" is
- "complex short int". */
-
- if (defaulted_int && ! longlong
- && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_SIGNED)
- | (1 << (int) RID_UNSIGNED))))
- {
- if (pedantic)
- pedwarn ("ISO C does not support plain `complex' meaning `double complex'");
- type = complex_double_type_node;
- }
- else if (type == integer_type_node)
- {
- if (pedantic)
- pedwarn ("ISO C does not support complex integer types");
- type = complex_integer_type_node;
- }
- else if (type == float_type_node)
- type = complex_float_type_node;
- else if (type == double_type_node)
- type = complex_double_type_node;
- else if (type == long_double_type_node)
- type = complex_long_double_type_node;
- else
- {
- if (pedantic)
- pedwarn ("ISO C does not support complex integer types");
- type = build_complex_type (type);
- }
- }
+ /* Adjust the type if a bit-field is being declared,
+ -funsigned-bitfields applied and the type is not explicitly
+ "signed". */
+ if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p
+ && TREE_CODE (type) == INTEGER_TYPE)
+ type = c_common_unsigned_type (type);
/* Figure out the type qualifiers for the declaration. There are
two ways a declaration can become qualified. One is something
@@ -3657,141 +4001,132 @@ grokdeclarator (tree declarator, tree declspecs,
duplicate qualifiers should be diagnosed in this case, but it
seems most appropriate to do so). */
element_type = strip_array_types (type);
- constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (element_type);
- restrictp
- = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (element_type);
- volatilep
- = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (element_type);
- inlinep = !! (specbits & (1 << (int) RID_INLINE));
+ constp = declspecs->const_p + TYPE_READONLY (element_type);
+ restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
+ volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
if (pedantic && !flag_isoc99)
{
if (constp > 1)
- pedwarn ("duplicate `const'");
+ pedwarn ("duplicate %<const%>");
if (restrictp > 1)
- pedwarn ("duplicate `restrict'");
+ pedwarn ("duplicate %<restrict%>");
if (volatilep > 1)
- pedwarn ("duplicate `volatile'");
+ pedwarn ("duplicate %<volatile%>");
}
- if (! flag_gen_aux_info && (TYPE_QUALS (type)))
+ if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
type = TYPE_MAIN_VARIANT (type);
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
- /* Warn if two storage classes are given. Default to `auto'. */
-
- {
- int nclasses = 0;
-
- if (specbits & 1 << (int) RID_AUTO) nclasses++;
- if (specbits & 1 << (int) RID_STATIC) nclasses++;
- if (specbits & 1 << (int) RID_EXTERN) nclasses++;
- if (specbits & 1 << (int) RID_REGISTER) nclasses++;
- if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
-
- /* "static __thread" and "extern __thread" are allowed. */
- if ((specbits & (1 << (int) RID_THREAD
- | 1 << (int) RID_STATIC
- | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
- nclasses++;
-
- /* Warn about storage classes that are invalid for certain
- kinds of declarations (parameters, typenames, etc.). */
-
- if (nclasses > 1)
- error ("multiple storage classes in declaration of `%s'", name);
- else if (funcdef_flag
- && (specbits
- & ((1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO)
- | (1 << (int) RID_TYPEDEF)
- | (1 << (int) RID_THREAD))))
- {
- if (specbits & 1 << (int) RID_AUTO
- && (pedantic || current_scope == global_scope))
- pedwarn ("function definition declared `auto'");
- if (specbits & 1 << (int) RID_REGISTER)
- error ("function definition declared `register'");
- if (specbits & 1 << (int) RID_TYPEDEF)
- error ("function definition declared `typedef'");
- if (specbits & 1 << (int) RID_THREAD)
- error ("function definition declared `__thread'");
- specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
- }
- else if (decl_context != NORMAL && nclasses > 0)
- {
- if (decl_context == PARM && specbits & 1 << (int) RID_REGISTER)
- ;
- else
- {
- switch (decl_context)
- {
- case FIELD:
- error ("storage class specified for structure field `%s'",
- name);
- break;
- case PARM:
- error ("storage class specified for parameter `%s'", name);
- break;
- default:
- error ("storage class specified for typename");
- break;
- }
- specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
- | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
- }
- }
- else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
- {
- /* `extern' with initialization is invalid if not at file scope. */
- if (current_scope == global_scope)
- warning ("`%s' initialized and declared `extern'", name);
- else
- error ("`%s' has both `extern' and initializer", name);
- }
- else if (current_scope == global_scope)
- {
- if (specbits & 1 << (int) RID_AUTO)
- error ("file-scope declaration of `%s' specifies `auto'", name);
- }
- else
- {
- if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
- error ("nested function `%s' declared `extern'", name);
- else if ((specbits & (1 << (int) RID_THREAD
- | 1 << (int) RID_EXTERN
- | 1 << (int) RID_STATIC))
- == (1 << (int) RID_THREAD))
- {
- error ("function-scope `%s' implicitly auto and declared `__thread'",
- name);
- specbits &= ~(1 << (int) RID_THREAD);
- }
- }
- }
+ /* Warn about storage classes that are invalid for certain
+ kinds of declarations (parameters, typenames, etc.). */
+
+ if (funcdef_flag
+ && (threadp
+ || storage_class == csc_auto
+ || storage_class == csc_register
+ || storage_class == csc_typedef))
+ {
+ if (storage_class == csc_auto
+ && (pedantic || current_scope == file_scope))
+ pedwarn ("function definition declared %<auto%>");
+ if (storage_class == csc_register)
+ error ("function definition declared %<register%>");
+ if (storage_class == csc_typedef)
+ error ("function definition declared %<typedef%>");
+ if (threadp)
+ error ("function definition declared %<__thread%>");
+ threadp = false;
+ if (storage_class == csc_auto
+ || storage_class == csc_register
+ || storage_class == csc_typedef)
+ storage_class = csc_none;
+ }
+ else if (decl_context != NORMAL && (storage_class != csc_none || threadp))
+ {
+ if (decl_context == PARM && storage_class == csc_register)
+ ;
+ else
+ {
+ switch (decl_context)
+ {
+ case FIELD:
+ error ("storage class specified for structure field %qs",
+ name);
+ break;
+ case PARM:
+ error ("storage class specified for parameter %qs", name);
+ break;
+ default:
+ error ("storage class specified for typename");
+ break;
+ }
+ storage_class = csc_none;
+ threadp = false;
+ }
+ }
+ else if (storage_class == csc_extern
+ && initialized
+ && !funcdef_flag)
+ {
+ /* 'extern' with initialization is invalid if not at file scope. */
+ if (current_scope == file_scope)
+ {
+ /* It is fine to have 'extern const' when compiling at C
+ and C++ intersection. */
+ if (!(warn_cxx_compat && constp))
+ warning (0, "%qs initialized and declared %<extern%>", name);
+ }
+ else
+ error ("%qs has both %<extern%> and initializer", name);
+ }
+ else if (current_scope == file_scope)
+ {
+ if (storage_class == csc_auto)
+ error ("file-scope declaration of %qs specifies %<auto%>", name);
+ if (pedantic && storage_class == csc_register)
+ pedwarn ("file-scope declaration of %qs specifies %<register%>", name);
+ }
+ else
+ {
+ if (storage_class == csc_extern && funcdef_flag)
+ error ("nested function %qs declared %<extern%>", name);
+ else if (threadp && storage_class == csc_none)
+ {
+ error ("function-scope %qs implicitly auto and declared "
+ "%<__thread%>",
+ name);
+ threadp = false;
+ }
+ }
/* Now figure out the structure of the declarator proper.
Descend through it, creating more complex types, until we reach
- the declared identifier (or NULL_TREE, in an absolute declarator). */
+ the declared identifier (or NULL_TREE, in an absolute declarator).
+ At each stage we maintain an unqualified version of the type
+ together with any qualifiers that should be applied to it with
+ c_build_qualified_type; this way, array types including
+ multidimensional array types are first built up in unqualified
+ form and then the qualified form is created with
+ TYPE_MAIN_VARIANT pointing to the unqualified form. */
- while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
+ while (declarator && declarator->kind != cdk_id)
{
if (type == error_mark_node)
{
- declarator = TREE_OPERAND (declarator, 0);
+ declarator = declarator->declarator;
continue;
}
- /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
- an INDIRECT_REF (for *...),
- a CALL_EXPR (for ...(...)),
- a TREE_LIST (for nested attributes),
- an identifier (for the name being declared)
- or a null pointer (for the place in an absolute declarator
+ /* Each level of DECLARATOR is either a cdk_array (for ...[..]),
+ a cdk_pointer (for *...),
+ a cdk_function (for ...(...)),
+ a cdk_attrs (for nested attributes),
+ or a cdk_id (for the name being declared
+ or the place in an absolute declarator
where the name was omitted).
- For the last two cases, we have just exited the loop.
+ For the last case, we have just exited the loop.
At this point, TYPE is the type of elements of an array,
or for a function to return, or for a pointer to point to.
@@ -3799,360 +4134,410 @@ grokdeclarator (tree declarator, tree declspecs,
array or function or pointer, and DECLARATOR has had its
outermost layer removed. */
- if (array_ptr_quals != NULL_TREE || array_parm_static)
+ if (array_ptr_quals != TYPE_UNQUALIFIED
+ || array_ptr_attrs != NULL_TREE
+ || array_parm_static)
{
/* Only the innermost declarator (making a parameter be of
array type which is converted to pointer type)
may have static or type qualifiers. */
error ("static or type qualifiers in non-parameter array declarator");
- array_ptr_quals = NULL_TREE;
+ array_ptr_quals = TYPE_UNQUALIFIED;
+ array_ptr_attrs = NULL_TREE;
array_parm_static = 0;
}
- if (TREE_CODE (declarator) == TREE_LIST)
- {
- /* We encode a declarator with embedded attributes using
- a TREE_LIST. */
- tree attrs = TREE_PURPOSE (declarator);
- tree inner_decl;
- int attr_flags = 0;
- declarator = TREE_VALUE (declarator);
- inner_decl = declarator;
- while (inner_decl != NULL_TREE
- && TREE_CODE (inner_decl) == TREE_LIST)
- inner_decl = TREE_VALUE (inner_decl);
- if (inner_decl == NULL_TREE
- || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
- attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
- else if (TREE_CODE (inner_decl) == CALL_EXPR)
- attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
- else if (TREE_CODE (inner_decl) == ARRAY_REF)
- attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
- returned_attrs = decl_attributes (&type,
- chainon (returned_attrs, attrs),
- attr_flags);
- }
- else if (TREE_CODE (declarator) == ARRAY_REF)
+ switch (declarator->kind)
{
- tree itype = NULL_TREE;
- tree size = TREE_OPERAND (declarator, 1);
- /* The index is a signed object `sizetype' bits wide. */
- tree index_type = c_common_signed_type (sizetype);
+ case cdk_attrs:
+ {
+ /* A declarator with embedded attributes. */
+ tree attrs = declarator->u.attrs;
+ const struct c_declarator *inner_decl;
+ int attr_flags = 0;
+ declarator = declarator->declarator;
+ inner_decl = declarator;
+ while (inner_decl->kind == cdk_attrs)
+ inner_decl = inner_decl->declarator;
+ if (inner_decl->kind == cdk_id)
+ attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+ else if (inner_decl->kind == cdk_function)
+ attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+ else if (inner_decl->kind == cdk_array)
+ attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
+ break;
+ }
+ case cdk_array:
+ {
+ tree itype = NULL_TREE;
+ tree size = declarator->u.array.dimen;
+ /* The index is a signed object `sizetype' bits wide. */
+ tree index_type = c_common_signed_type (sizetype);
- array_ptr_quals = TREE_TYPE (declarator);
- array_parm_static = TREE_STATIC (declarator);
+ array_ptr_quals = declarator->u.array.quals;
+ array_ptr_attrs = declarator->u.array.attrs;
+ array_parm_static = declarator->u.array.static_p;
+ array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p;
- declarator = TREE_OPERAND (declarator, 0);
+ declarator = declarator->declarator;
- /* Check for some types that there cannot be arrays of. */
+ /* Check for some types that there cannot be arrays of. */
- if (VOID_TYPE_P (type))
- {
- error ("declaration of `%s' as array of voids", name);
- type = error_mark_node;
- }
+ if (VOID_TYPE_P (type))
+ {
+ error ("declaration of %qs as array of voids", name);
+ type = error_mark_node;
+ }
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("declaration of `%s' as array of functions", name);
- type = error_mark_node;
- }
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error ("declaration of %qs as array of functions", name);
+ type = error_mark_node;
+ }
- if (pedantic && !in_system_header && flexible_array_type_p (type))
- pedwarn ("invalid use of structure with flexible array member");
+ if (pedantic && !in_system_header && flexible_array_type_p (type))
+ pedwarn ("invalid use of structure with flexible array member");
- if (size == error_mark_node)
- type = error_mark_node;
+ if (size == error_mark_node)
+ type = error_mark_node;
- if (type == error_mark_node)
- continue;
+ if (type == error_mark_node)
+ continue;
- /* If size was specified, set ITYPE to a range-type for that size.
- Otherwise, ITYPE remains null. finish_decl may figure it out
- from an initial value. */
+ /* If size was specified, set ITYPE to a range-type for
+ that size. Otherwise, ITYPE remains null. finish_decl
+ may figure it out from an initial value. */
- if (size)
- {
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
- STRIP_TYPE_NOPS (size);
+ if (size)
+ {
+ /* Strip NON_LVALUE_EXPRs since we aren't using as an
+ lvalue. */
+ STRIP_TYPE_NOPS (size);
- if (! INTEGRAL_TYPE_P (TREE_TYPE (size)))
- {
- error ("size of array `%s' has non-integer type", name);
- size = integer_one_node;
- }
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
+ {
+ error ("size of array %qs has non-integer type", name);
+ size = integer_one_node;
+ }
- if (pedantic && integer_zerop (size))
- pedwarn ("ISO C forbids zero-size array `%s'", name);
+ if (pedantic && integer_zerop (size))
+ pedwarn ("ISO C forbids zero-size array %qs", name);
- if (TREE_CODE (size) == INTEGER_CST)
- {
- constant_expression_warning (size);
- if (tree_int_cst_sgn (size) < 0)
- {
- error ("size of array `%s' is negative", name);
- size = integer_one_node;
- }
- }
- else
- {
- /* Make sure the array size remains visibly nonconstant
- even if it is (eg) a const variable with known value. */
- size_varies = 1;
+ if (TREE_CODE (size) == INTEGER_CST)
+ {
+ constant_expression_warning (size);
+ if (tree_int_cst_sgn (size) < 0)
+ {
+ error ("size of array %qs is negative", name);
+ size = integer_one_node;
+ }
+ }
+ else if ((decl_context == NORMAL || decl_context == FIELD)
+ && current_scope == file_scope)
+ {
+ error ("variably modified %qs at file scope", name);
+ size = integer_one_node;
+ }
+ else
+ {
+ /* Make sure the array size remains visibly
+ nonconstant even if it is (eg) a const variable
+ with known value. */
+ size_varies = 1;
- if (!flag_isoc99 && pedantic)
- {
- if (TREE_CONSTANT (size))
- pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated",
- name);
- else
- pedwarn ("ISO C90 forbids variable-size array `%s'",
- name);
- }
- }
+ if (!flag_isoc99 && pedantic)
+ {
+ if (TREE_CONSTANT (size))
+ pedwarn ("ISO C90 forbids array %qs whose size "
+ "can%'t be evaluated",
+ name);
+ else
+ pedwarn ("ISO C90 forbids variable-size array %qs",
+ name);
+ }
+ }
- if (integer_zerop (size))
- {
- /* A zero-length array cannot be represented with an
- unsigned index type, which is what we'll get with
- build_index_type. Create an open-ended range instead. */
- itype = build_range_type (sizetype, size, NULL_TREE);
- }
- else
- {
- /* Compute the maximum valid index, that is, size - 1.
- Do the calculation in index_type, so that if it is
- a variable the computations will be done in the
- proper mode. */
- itype = fold (build (MINUS_EXPR, index_type,
- convert (index_type, size),
- convert (index_type, size_one_node)));
-
- /* If that overflowed, the array is too big.
- ??? While a size of INT_MAX+1 technically shouldn't
- cause an overflow (because we subtract 1), the overflow
- is recorded during the conversion to index_type, before
- the subtraction. Handling this case seems like an
- unnecessary complication. */
- if (TREE_OVERFLOW (itype))
- {
- error ("size of array `%s' is too large", name);
- type = error_mark_node;
- continue;
- }
+ if (integer_zerop (size))
+ {
+ /* A zero-length array cannot be represented with
+ an unsigned index type, which is what we'll
+ get with build_index_type. Create an
+ open-ended range instead. */
+ itype = build_range_type (sizetype, size, NULL_TREE);
+ }
+ else
+ {
+ /* Arrange for the SAVE_EXPR on the inside of the
+ MINUS_EXPR, which allows the -1 to get folded
+ with the +1 that happens when building TYPE_SIZE. */
+ if (size_varies)
+ size = variable_size (size);
+
+ /* Compute the maximum valid index, that is, size
+ - 1. Do the calculation in index_type, so that
+ if it is a variable the computations will be
+ done in the proper mode. */
+ itype = fold_build2 (MINUS_EXPR, index_type,
+ convert (index_type, size),
+ convert (index_type,
+ size_one_node));
+
+ /* If that overflowed, the array is too big. ???
+ While a size of INT_MAX+1 technically shouldn't
+ cause an overflow (because we subtract 1), the
+ overflow is recorded during the conversion to
+ index_type, before the subtraction. Handling
+ this case seems like an unnecessary
+ complication. */
+ if (TREE_CODE (itype) == INTEGER_CST
+ && TREE_OVERFLOW (itype))
+ {
+ error ("size of array %qs is too large", name);
+ type = error_mark_node;
+ continue;
+ }
- if (size_varies)
- {
- /* We must be able to distinguish the
- SAVE_EXPR_CONTEXT for the variably-sized type
- so that we can set it correctly in
- set_save_expr_context. The convention is
- that all SAVE_EXPRs that need to be reset
- have NULL_TREE for their SAVE_EXPR_CONTEXT. */
- tree cfd = current_function_decl;
- if (decl_context == PARM)
- current_function_decl = NULL_TREE;
- itype = variable_size (itype);
- if (decl_context == PARM)
- current_function_decl = cfd;
- }
- itype = build_index_type (itype);
- }
- }
- else if (decl_context == FIELD)
- {
- if (pedantic && !flag_isoc99 && !in_system_header)
- pedwarn ("ISO C90 does not support flexible array members");
+ itype = build_index_type (itype);
+ }
+ }
+ else if (decl_context == FIELD)
+ {
+ if (pedantic && !flag_isoc99 && !in_system_header)
+ pedwarn ("ISO C90 does not support flexible array members");
- /* ISO C99 Flexible array members are effectively identical
- to GCC's zero-length array extension. */
- itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
- }
+ /* ISO C99 Flexible array members are effectively
+ identical to GCC's zero-length array extension. */
+ itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ }
+ else if (decl_context == PARM)
+ {
+ if (array_parm_vla_unspec_p)
+ {
+ if (! orig_name)
+ {
+ /* C99 6.7.5.2p4 */
+ error ("%<[*]%> not allowed in other than a declaration");
+ }
- /* If pedantic, complain about arrays of incomplete types. */
+ itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ size_varies = 1;
+ }
+ }
+ else if (decl_context == TYPENAME)
+ {
+ if (array_parm_vla_unspec_p)
+ {
+ /* The error is printed elsewhere. We use this to
+ avoid messing up with incomplete array types of
+ the same type, that would otherwise be modified
+ below. */
+ itype = build_range_type (sizetype, size_zero_node,
+ NULL_TREE);
+ }
+ }
- if (pedantic && !COMPLETE_TYPE_P (type))
- pedwarn ("array type has incomplete element type");
+ /* Complain about arrays of incomplete types. */
+ if (!COMPLETE_TYPE_P (type))
+ {
+ error ("array type has incomplete element type");
+ type = error_mark_node;
+ }
+ else
+ /* When itype is NULL, a shared incomplete array type is
+ returned for all array of a given type. Elsewhere we
+ make sure we don't complete that type before copying
+ it, but here we want to make sure we don't ever
+ modify the shared type, so we gcc_assert (itype)
+ below. */
+ type = build_array_type (type, itype);
+
+ if (type != error_mark_node)
+ {
+ if (size_varies)
+ {
+ /* It is ok to modify type here even if itype is
+ NULL: if size_varies, we're in a
+ multi-dimensional array and the inner type has
+ variable size, so the enclosing shared array type
+ must too. */
+ if (size && TREE_CODE (size) == INTEGER_CST)
+ type
+ = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+ C_TYPE_VARIABLE_SIZE (type) = 1;
+ }
- /* Build the array type itself, then merge any constancy or
- volatility into the target type. We must do it in this order
- to ensure that the TYPE_MAIN_VARIANT field of the array type
- is set correctly. */
+ /* The GCC extension for zero-length arrays differs from
+ ISO flexible array members in that sizeof yields
+ zero. */
+ if (size && integer_zerop (size))
+ {
+ gcc_assert (itype);
+ TYPE_SIZE (type) = bitsize_zero_node;
+ TYPE_SIZE_UNIT (type) = size_zero_node;
+ }
+ if (array_parm_vla_unspec_p)
+ {
+ gcc_assert (itype);
+ /* The type is complete. C99 6.7.5.2p4 */
+ TYPE_SIZE (type) = bitsize_zero_node;
+ TYPE_SIZE_UNIT (type) = size_zero_node;
+ }
+ }
- type = build_array_type (type, itype);
- if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ if (decl_context != PARM
+ && (array_ptr_quals != TYPE_UNQUALIFIED
+ || array_ptr_attrs != NULL_TREE
+ || array_parm_static))
+ {
+ error ("static or type qualifiers in non-parameter array declarator");
+ array_ptr_quals = TYPE_UNQUALIFIED;
+ array_ptr_attrs = NULL_TREE;
+ array_parm_static = 0;
+ }
+ break;
+ }
+ case cdk_function:
+ {
+ /* Say it's a definition only for the declarator closest
+ to the identifier, apart possibly from some
+ attributes. */
+ bool really_funcdef = false;
+ tree arg_types;
+ if (funcdef_flag)
+ {
+ const struct c_declarator *t = declarator->declarator;
+ while (t->kind == cdk_attrs)
+ t = t->declarator;
+ really_funcdef = (t->kind == cdk_id);
+ }
- if (size_varies)
- C_TYPE_VARIABLE_SIZE (type) = 1;
+ /* Declaring a function type. Make sure we have a valid
+ type for the function to return. */
+ if (type == error_mark_node)
+ continue;
- /* The GCC extension for zero-length arrays differs from
- ISO flexible array members in that sizeof yields zero. */
- if (size && integer_zerop (size))
- {
- layout_type (type);
- TYPE_SIZE (type) = bitsize_zero_node;
- TYPE_SIZE_UNIT (type) = size_zero_node;
- }
- if (decl_context != PARM
- && (array_ptr_quals != NULL_TREE || array_parm_static))
- {
- error ("static or type qualifiers in non-parameter array declarator");
- array_ptr_quals = NULL_TREE;
- array_parm_static = 0;
- }
- }
- else if (TREE_CODE (declarator) == CALL_EXPR)
- {
- /* Say it's a definition only for the declarator closest to
- the identifier, apart possibly from some attributes. */
- bool really_funcdef = false;
- tree arg_types;
- if (funcdef_flag)
- {
- tree t = TREE_OPERAND (declarator, 0);
- while (TREE_CODE (t) == TREE_LIST)
- t = TREE_VALUE (t);
- really_funcdef = (TREE_CODE (t) == IDENTIFIER_NODE);
- }
+ size_varies = 0;
- /* Declaring a function type.
- Make sure we have a valid type for the function to return. */
- if (type == error_mark_node)
- continue;
+ /* Warn about some types functions can't return. */
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error ("%qs declared as function returning a function", name);
+ type = integer_type_node;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ error ("%qs declared as function returning an array", name);
+ type = integer_type_node;
+ }
- size_varies = 0;
+ /* Construct the function type and go to the next
+ inner layer of declarator. */
+ arg_info = declarator->u.arg_info;
+ arg_types = grokparms (arg_info, really_funcdef);
+ if (really_funcdef)
+ put_pending_sizes (arg_info->pending_sizes);
- /* Warn about some types functions can't return. */
+ /* Type qualifiers before the return type of the function
+ qualify the return type, not the function type. */
+ if (type_quals)
+ {
+ /* Type qualifiers on a function return type are
+ normally permitted by the standard but have no
+ effect, so give a warning at -Wreturn-type.
+ Qualifiers on a void return type are banned on
+ function definitions in ISO C; GCC used to used
+ them for noreturn functions. */
+ if (VOID_TYPE_P (type) && really_funcdef)
+ pedwarn ("function definition has qualified void return type");
+ else
+ warning (OPT_Wreturn_type,
+ "type qualifiers ignored on function return type");
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("`%s' declared as function returning a function", name);
- type = integer_type_node;
- }
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- error ("`%s' declared as function returning an array", name);
- type = integer_type_node;
- }
+ type = c_build_qualified_type (type, type_quals);
+ }
+ type_quals = TYPE_UNQUALIFIED;
- /* Construct the function type and go to the next
- inner layer of declarator. */
+ type = build_function_type (type, arg_types);
+ declarator = declarator->declarator;
- arg_types = grokparms (TREE_OPERAND (declarator, 1),
- really_funcdef);
- /* Type qualifiers before the return type of the function
- qualify the return type, not the function type. */
- if (type_quals)
+ /* Set the TYPE_CONTEXTs for each tagged type which is local to
+ the formal parameter list of this FUNCTION_TYPE to point to
+ the FUNCTION_TYPE node itself. */
{
- /* Type qualifiers on a function return type are normally
- permitted by the standard but have no effect, so give a
- warning at -Wextra. Qualifiers on a void return type have
- meaning as a GNU extension, and are banned on function
- definitions in ISO C. FIXME: strictly we shouldn't
- pedwarn for qualified void return types except on function
- definitions, but not doing so could lead to the undesirable
- state of a "volatile void" function return type not being
- warned about, and a use of the function being compiled
- with GNU semantics, with no diagnostics under -pedantic. */
- if (VOID_TYPE_P (type) && pedantic && !in_system_header)
- pedwarn ("ISO C forbids qualified void function return type");
- else if (extra_warnings
- && !(VOID_TYPE_P (type)
- && type_quals == TYPE_QUAL_VOLATILE))
- warning ("type qualifiers ignored on function return type");
+ tree link;
- type = c_build_qualified_type (type, type_quals);
+ for (link = arg_info->tags;
+ link;
+ link = TREE_CHAIN (link))
+ TYPE_CONTEXT (TREE_VALUE (link)) = type;
}
- type_quals = TYPE_UNQUALIFIED;
-
- type = build_function_type (type, arg_types);
- declarator = TREE_OPERAND (declarator, 0);
-
- /* Set the TYPE_CONTEXTs for each tagged type which is local to
- the formal parameter list of this FUNCTION_TYPE to point to
- the FUNCTION_TYPE node itself. */
-
- {
- tree link;
-
- for (link = last_function_parm_tags;
- link;
- link = TREE_CHAIN (link))
- TYPE_CONTEXT (TREE_VALUE (link)) = type;
+ break;
}
- }
- else if (TREE_CODE (declarator) == INDIRECT_REF)
- {
- /* Merge any constancy or volatility into the target type
- for the pointer. */
-
- if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && type_quals)
- pedwarn ("ISO C forbids qualified function types");
- if (type_quals)
- type = c_build_qualified_type (type, type_quals);
- type_quals = TYPE_UNQUALIFIED;
- size_varies = 0;
-
- type = build_pointer_type (type);
-
- /* Process a list of type modifier keywords
- (such as const or volatile) that were given inside the `*'. */
+ case cdk_pointer:
+ {
+ /* Merge any constancy or volatility into the target type
+ for the pointer. */
- if (TREE_TYPE (declarator))
- {
- tree typemodlist;
- int erred = 0;
-
- constp = 0;
- volatilep = 0;
- restrictp = 0;
- for (typemodlist = TREE_TYPE (declarator); typemodlist;
- typemodlist = TREE_CHAIN (typemodlist))
- {
- tree qualifier = TREE_VALUE (typemodlist);
+ if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals)
+ pedwarn ("ISO C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+ size_varies = 0;
- if (C_IS_RESERVED_WORD (qualifier))
- {
- if (C_RID_CODE (qualifier) == RID_CONST)
- constp++;
- else if (C_RID_CODE (qualifier) == RID_VOLATILE)
- volatilep++;
- else if (C_RID_CODE (qualifier) == RID_RESTRICT)
- restrictp++;
- else
- erred++;
- }
- else
- erred++;
- }
+ /* When the pointed-to type involves components of variable size,
+ care must be taken to ensure that the size evaluation code is
+ emitted early enough to dominate all the possible later uses
+ and late enough for the variables on which it depends to have
+ been assigned.
+
+ This is expected to happen automatically when the pointed-to
+ type has a name/declaration of it's own, but special attention
+ is required if the type is anonymous.
+
+ We handle the NORMAL and FIELD contexts here by attaching an
+ artificial TYPE_DECL to such pointed-to type. This forces the
+ sizes evaluation at a safe point and ensures it is not deferred
+ until e.g. within a deeper conditional context.
+
+ We expect nothing to be needed here for PARM or TYPENAME.
+ Pushing a TYPE_DECL at this point for TYPENAME would actually
+ be incorrect, as we might be in the middle of an expression
+ with side effects on the pointed-to type size "arguments" prior
+ to the pointer declaration point and the fake TYPE_DECL in the
+ enclosing context would force the size evaluation prior to the
+ side effects. */
+
+ if (!TYPE_NAME (type)
+ && (decl_context == NORMAL || decl_context == FIELD)
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ tree decl = build_decl (TYPE_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (decl) = 1;
+ pushdecl (decl);
+ finish_decl (decl, NULL_TREE, NULL_TREE);
+ TYPE_NAME (type) = decl;
+ }
- if (erred)
- error ("invalid type modifier within pointer declarator");
- if (pedantic && !flag_isoc99)
- {
- if (constp > 1)
- pedwarn ("duplicate `const'");
- if (volatilep > 1)
- pedwarn ("duplicate `volatile'");
- if (restrictp > 1)
- pedwarn ("duplicate `restrict'");
- }
+ type = build_pointer_type (type);
- type_quals = ((constp ? TYPE_QUAL_CONST : 0)
- | (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
- }
+ /* Process type qualifiers (such as const or volatile)
+ that were given inside the `*'. */
+ type_quals = declarator->u.pointer_quals;
- declarator = TREE_OPERAND (declarator, 0);
+ declarator = declarator->declarator;
+ break;
+ }
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
-
}
- /* Now TYPE has the actual type. */
+ /* Now TYPE has the actual type, apart from any qualifiers in
+ TYPE_QUALS. */
/* Check the type and width of a bit-field. */
if (bitfield)
@@ -4162,9 +4547,10 @@ grokdeclarator (tree declarator, tree declspecs,
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
- && TREE_OVERFLOW (TYPE_SIZE (type)))
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
+ && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
{
- error ("size of array `%s' is too large", name);
+ error ("size of array %qs is too large", name);
/* If we proceed with the array type as it is, we'll eventually
crash in tree_low_cst(). */
type = error_mark_node;
@@ -4172,46 +4558,32 @@ grokdeclarator (tree declarator, tree declspecs,
/* If this is declaring a typedef name, return a TYPE_DECL. */
- if (specbits & (1 << (int) RID_TYPEDEF))
+ if (storage_class == csc_typedef)
{
tree decl;
- /* Note that the grammar rejects storage classes
- in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- decl = build_decl (TYPE_DECL, declarator, type);
- if ((specbits & (1 << (int) RID_SIGNED))
- || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
+ decl = build_decl (TYPE_DECL, declarator->u.id, type);
+ if (declspecs->explicit_signed_p)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
decl_attributes (&decl, returned_attrs, 0);
+ if (declspecs->inline_p)
+ pedwarn ("typedef %q+D declared %<inline%>", decl);
return decl;
}
- /* Detect the case of an array type of unspecified size
- which came, as such, direct from a typedef name.
- We must copy the type, so that each identifier gets
- a distinct type, so that each identifier's size can be
- controlled separately by its own initializer. */
-
- if (type != 0 && typedef_type != 0
- && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
- {
- type = build_array_type (TREE_TYPE (type), 0);
- if (size_varies)
- C_TYPE_VARIABLE_SIZE (type) = 1;
- }
-
/* If this is a type name (such as, in a cast or sizeof),
compute the type and return it now. */
if (decl_context == TYPENAME)
{
- /* Note that the grammar rejects storage classes
- in typenames, fields or parameters */
+ /* Note that the grammar rejects storage classes in typenames
+ and fields. */
+ gcc_assert (storage_class == csc_none && !threadp
+ && !declspecs->inline_p);
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
pedwarn ("ISO C forbids const or volatile function types");
@@ -4221,6 +4593,13 @@ grokdeclarator (tree declarator, tree declspecs,
return type;
}
+ if (pedantic && decl_context == FIELD
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ /* C99 6.7.2.1p8 */
+ pedwarn ("a member of a structure or union cannot have a variably modified type");
+ }
+
/* Aside from typedefs and type names (handle above),
`void' at top level (not within pointer)
is allowed only in public variables.
@@ -4228,13 +4607,13 @@ grokdeclarator (tree declarator, tree declspecs,
a better error message can be made later. */
if (VOID_TYPE_P (type) && decl_context != PARM
- && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
- && ((specbits & (1 << (int) RID_EXTERN))
- || (current_scope == global_scope
- && !(specbits
- & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
+ && !((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
+ && (storage_class == csc_extern
+ || (current_scope == file_scope
+ && !(storage_class == csc_static
+ || storage_class == csc_register)))))
{
- error ("variable or field `%s' declared void", name);
+ error ("variable or field %qs declared void", name);
type = integer_type_node;
}
@@ -4259,45 +4638,13 @@ grokdeclarator (tree declarator, tree declspecs,
if (type_quals)
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
- type_quals = TYPE_UNQUALIFIED;
- if (array_ptr_quals)
- {
- tree new_ptr_quals, new_ptr_attrs;
- int erred = 0;
- split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs);
- /* We don't yet implement attributes in this context. */
- if (new_ptr_attrs != NULL_TREE)
- warning ("attributes in parameter array declarator ignored");
-
- constp = 0;
- volatilep = 0;
- restrictp = 0;
- for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals))
- {
- tree qualifier = TREE_VALUE (new_ptr_quals);
+ type_quals = array_ptr_quals;
- if (C_IS_RESERVED_WORD (qualifier))
- {
- if (C_RID_CODE (qualifier) == RID_CONST)
- constp++;
- else if (C_RID_CODE (qualifier) == RID_VOLATILE)
- volatilep++;
- else if (C_RID_CODE (qualifier) == RID_RESTRICT)
- restrictp++;
- else
- erred++;
- }
- else
- erred++;
- }
-
- if (erred)
- error ("invalid type modifier within array declarator");
+ /* We don't yet implement attributes in this context. */
+ if (array_ptr_attrs != NULL_TREE)
+ warning (OPT_Wattributes,
+ "attributes in parameter array declarator ignored");
- type_quals = ((constp ? TYPE_QUAL_CONST : 0)
- | (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
- }
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -4314,7 +4661,7 @@ grokdeclarator (tree declarator, tree declspecs,
type_as_written = type;
- decl = build_decl (PARM_DECL, declarator, type);
+ decl = build_decl (PARM_DECL, declarator->u.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -4329,29 +4676,31 @@ grokdeclarator (tree declarator, tree declspecs,
promoted_type = c_type_promotes_to (type);
DECL_ARG_TYPE (decl) = promoted_type;
- DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
+ if (declspecs->inline_p)
+ pedwarn ("parameter %q+D declared %<inline%>", decl);
}
else if (decl_context == FIELD)
{
+ /* Note that the grammar rejects storage classes in typenames
+ and fields. */
+ gcc_assert (storage_class == csc_none && !threadp
+ && !declspecs->inline_p);
+
/* Structure field. It may not be a function. */
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("field `%s' declared as a function", name);
+ error ("field %qs declared as a function", name);
type = build_pointer_type (type);
}
else if (TREE_CODE (type) != ERROR_MARK
- && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
+ && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
{
- error ("field `%s' has incomplete type", name);
+ error ("field %qs has incomplete type", name);
type = error_mark_node;
}
- /* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
- type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
- decl = build_decl (FIELD_DECL, declarator, type);
+ type = c_build_qualified_type (type, type_quals);
+ decl = build_decl (FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (size_varies)
@@ -4359,60 +4708,75 @@ grokdeclarator (tree declarator, tree declspecs,
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- /* Every function declaration is "external"
- except for those which are inside a function body
- in which `auto' is used.
- That is a case not specified by ANSI C,
- and we use it for forward declarations for nested functions. */
- int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
- || current_scope == global_scope);
-
- if (specbits & (1 << (int) RID_AUTO)
- && (pedantic || current_scope == global_scope))
- pedwarn ("invalid storage class for function `%s'", name);
- if (specbits & (1 << (int) RID_REGISTER))
- error ("invalid storage class for function `%s'", name);
- if (specbits & (1 << (int) RID_THREAD))
- error ("invalid storage class for function `%s'", name);
- /* Function declaration not at file scope.
- Storage classes other than `extern' are not allowed
- and `extern' makes no difference. */
- if (current_scope != global_scope
- && (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE)))
- && pedantic)
- pedwarn ("invalid storage class for function `%s'", name);
-
- decl = build_decl (FUNCTION_DECL, declarator, type);
+ if (storage_class == csc_register || threadp)
+ {
+ error ("invalid storage class for function %qs", name);
+ }
+ else if (current_scope != file_scope)
+ {
+ /* Function declaration not at file scope. Storage
+ classes other than `extern' are not allowed, C99
+ 6.7.1p5, and `extern' makes no difference. However,
+ GCC allows 'auto', perhaps with 'inline', to support
+ nested functions. */
+ if (storage_class == csc_auto)
+ {
+ if (pedantic)
+ pedwarn ("invalid storage class for function %qs", name);
+ }
+ else if (storage_class == csc_static)
+ {
+ error ("invalid storage class for function %qs", name);
+ if (funcdef_flag)
+ storage_class = declspecs->storage_class = csc_none;
+ else
+ return 0;
+ }
+ }
+
+ decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
- DECL_LANG_SPECIFIC (decl)
- = ggc_alloc_cleared (sizeof (struct lang_decl));
+ DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
- if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+ if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
- /* GNU C interprets a `volatile void' return type to indicate
+ /* GNU C interprets a volatile-qualified function type to indicate
that the function does not return. */
if ((type_quals & TYPE_QUAL_VOLATILE)
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
- warning ("`noreturn' function returns non-void value");
-
- if (extern_ref)
+ warning (0, "%<noreturn%> function returns non-void value");
+
+ /* Every function declaration is an external reference
+ (DECL_EXTERNAL) except for those which are not at file
+ scope and are explicitly declared "auto". This is
+ forbidden by standard C (C99 6.7.1p5) and is interpreted by
+ GCC to signify a forward declaration of a nested function. */
+ if (storage_class == csc_auto && current_scope != file_scope)
+ DECL_EXTERNAL (decl) = 0;
+ else
DECL_EXTERNAL (decl) = 1;
+
/* Record absence of global scope for `static' or `auto'. */
TREE_PUBLIC (decl)
- = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
+ = !(storage_class == csc_static || storage_class == csc_auto);
+
+ /* For a function definition, record the argument information
+ block where store_parm_decls will look for it. */
+ if (funcdef_flag)
+ current_function_arg_info = arg_info;
- if (defaulted_int)
+ if (declspecs->default_int_p)
C_FUNCTION_IMPLICIT_INT (decl) = 1;
/* Record presence of `inline', if it is reasonable. */
- if (MAIN_NAME_P (declarator))
+ if (flag_hosted && MAIN_NAME_P (declarator->u.id))
{
- if (inlinep)
- warning ("cannot inline function `main'");
+ if (declspecs->inline_p)
+ pedwarn ("cannot inline function %<main%>");
}
- else if (inlinep)
+ else if (declspecs->inline_p)
{
/* Record that the function is declared `inline'. */
DECL_DECLARED_INLINE_P (decl) = 1;
@@ -4424,7 +4788,7 @@ grokdeclarator (tree declarator, tree declspecs,
if (initialized)
{
DECL_INLINE (decl) = 1;
- if (specbits & (1 << (int) RID_EXTERN))
+ if (storage_class == csc_extern)
current_extern_inline = 1;
}
}
@@ -4438,66 +4802,62 @@ grokdeclarator (tree declarator, tree declspecs,
{
/* It's a variable. */
/* An uninitialized decl with `extern' is a reference. */
- int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
+ int extern_ref = !initialized && storage_class == csc_extern;
- /* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
- {
- int saved_align = TYPE_ALIGN(type);
- type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
- TYPE_ALIGN (type) = saved_align;
- }
- else if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals);
- /* It is invalid to create an `extern' declaration for a
+ /* C99 6.2.2p7: It is invalid (compile-time undefined
+ behavior) to create an 'extern' declaration for a
variable if there is a global declaration that is
- `static' and the global declaration is not visible. */
- if (extern_ref && current_scope != global_scope)
+ 'static' and the global declaration is not visible.
+ (If the static declaration _is_ currently visible,
+ the 'extern' declaration is taken to refer to that decl.) */
+ if (extern_ref && current_scope != file_scope)
{
- tree global_decl;
+ tree global_decl = identifier_global_value (declarator->u.id);
+ tree visible_decl = lookup_name (declarator->u.id);
- global_decl = identifier_global_value (declarator);
if (global_decl
+ && global_decl != visible_decl
&& TREE_CODE (global_decl) == VAR_DECL
- && lookup_name (declarator) != global_decl
&& !TREE_PUBLIC (global_decl))
- error ("variable previously declared `static' redeclared "
- "`extern'");
+ error ("variable previously declared %<static%> redeclared "
+ "%<extern%>");
}
- decl = build_decl (VAR_DECL, declarator, type);
+ decl = build_decl (VAR_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
- if (inlinep)
- pedwarn ("%Jvariable '%D' declared `inline'", decl, decl);
+ if (declspecs->inline_p)
+ pedwarn ("variable %q+D declared %<inline%>", decl);
- DECL_EXTERNAL (decl) = extern_ref;
+ /* At file scope, an initialized extern declaration may follow
+ a static declaration. In that case, DECL_EXTERNAL will be
+ reset later in start_decl. */
+ DECL_EXTERNAL (decl) = (storage_class == csc_extern);
/* At file scope, the presence of a `static' or `register' storage
class specifier, or the absence of all storage class specifiers
makes this declaration a definition (perhaps tentative). Also,
- the absence of both `static' and `register' makes it public. */
- if (current_scope == global_scope)
+ the absence of `static' makes it public. */
+ if (current_scope == file_scope)
{
- TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
- | (1 << (int) RID_REGISTER)));
+ TREE_PUBLIC (decl) = storage_class != csc_static;
TREE_STATIC (decl) = !extern_ref;
}
/* Not at file scope, only `static' makes a static definition. */
else
{
- TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
+ TREE_STATIC (decl) = (storage_class == csc_static);
TREE_PUBLIC (decl) = extern_ref;
}
- if (specbits & 1 << (int) RID_THREAD)
+ if (threadp)
{
if (targetm.have_tls)
- DECL_THREAD_LOCAL (decl) = 1;
+ DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
else
/* A mere warning is sure to result in improper semantics
at runtime. Don't bother to allow this to compile. */
@@ -4505,27 +4865,46 @@ grokdeclarator (tree declarator, tree declspecs,
}
}
+ if (storage_class == csc_extern
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ /* C99 6.7.5.2p2 */
+ error ("object with variably modified type must have no linkage");
+ }
+
/* Record `register' declaration for warnings on &
and in case doing stupid register allocation. */
- if (specbits & (1 << (int) RID_REGISTER))
- DECL_REGISTER (decl) = 1;
+ if (storage_class == csc_register)
+ {
+ C_DECL_REGISTER (decl) = 1;
+ DECL_REGISTER (decl) = 1;
+ }
/* Record constancy and volatility. */
c_apply_type_quals_to_decl (type_quals, decl);
/* If a type has volatile components, it should be stored in memory.
Otherwise, the fact that those components are volatile
- will be ignored, and would even crash the compiler. */
- if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
- c_mark_addressable (decl);
+ will be ignored, and would even crash the compiler.
+ Of course, this only makes sense on VAR,PARM, and RESULT decl's. */
+ if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl))
+ && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == RESULT_DECL))
+ {
+ /* It is not an error for a structure with volatile fields to
+ be declared register, but reset DECL_REGISTER since it
+ cannot actually go in a register. */
+ int was_reg = C_DECL_REGISTER (decl);
+ C_DECL_REGISTER (decl) = 0;
+ DECL_REGISTER (decl) = 0;
+ c_mark_addressable (decl);
+ C_DECL_REGISTER (decl) = was_reg;
+ }
-#ifdef ENABLE_CHECKING
/* This is the earliest point at which we might know the assembler
name of a variable. Thus, if it's known before this, die horribly. */
- if (DECL_ASSEMBLER_NAME_SET_P (decl))
- abort ();
-#endif
+ gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
decl_attributes (&decl, returned_attrs, 0);
@@ -4534,218 +4913,295 @@ grokdeclarator (tree declarator, tree declspecs,
}
/* Decode the parameter-list info for a function type or function definition.
- The argument is the value returned by `get_parm_info' (or made in parse.y
+ The argument is the value returned by `get_parm_info' (or made in c-parse.c
if there is an identifier list instead of a parameter decl list).
These two functions are separate because when a function returns
or receives functions then each is called multiple times but the order
of calls is different. The last call to `grokparms' is always the one
that contains the formal parameter names of a function definition.
- Store in `last_function_parms' a chain of the decls of parms.
- Also store in `last_function_parm_tags' a chain of the struct, union,
- and enum tags declared among the parms.
-
Return a list of arg types to use in the FUNCTION_TYPE for this function.
- FUNCDEF_FLAG is nonzero for a function definition, 0 for
+ FUNCDEF_FLAG is true for a function definition, false for
a mere declaration. A nonempty identifier-list gets an error message
- when FUNCDEF_FLAG is zero. */
+ when FUNCDEF_FLAG is false. */
static tree
-grokparms (tree parms_info, int funcdef_flag)
+grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
{
- tree first_parm = TREE_CHAIN (parms_info);
+ tree arg_types = arg_info->types;
+
+ if (funcdef_flag && arg_info->had_vla_unspec)
+ {
+ /* A function definition isn't function prototype scope C99 6.2.1p4. */
+ /* C99 6.7.5.2p4 */
+ error ("%<[*]%> not allowed in other than function prototype scope");
+ }
- last_function_parms = TREE_PURPOSE (parms_info);
- last_function_parm_tags = TREE_VALUE (parms_info);
- last_function_parm_others = TREE_TYPE (parms_info);
+ if (arg_types == 0 && !funcdef_flag && !in_system_header)
+ warning (OPT_Wstrict_prototypes,
+ "function declaration isn%'t a prototype");
- if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag
- && !in_system_header)
- warning ("function declaration isn't a prototype");
+ if (arg_types == error_mark_node)
+ return 0; /* don't set TYPE_ARG_TYPES in this case */
- if (first_parm != 0
- && TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE)
+ else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
{
- if (! funcdef_flag)
+ if (!funcdef_flag)
pedwarn ("parameter names (without types) in function declaration");
- last_function_parms = first_parm;
+ arg_info->parms = arg_info->types;
+ arg_info->types = 0;
return 0;
}
else
{
- tree parm;
- tree typelt;
- /* If the arg types are incomplete in a declaration,
- they must include undefined tags.
- These tags can never be defined in the scope of the declaration,
- so the types can never be completed,
- and no call can be compiled successfully. */
+ tree parm, type, typelt;
+ unsigned int parmno;
+
+ /* If there is a parameter of incomplete type in a definition,
+ this is an error. In a declaration this is valid, and a
+ struct or union type may be completed later, before any calls
+ or definition of the function. In the case where the tag was
+ first declared within the parameter list, a warning has
+ already been given. If a parameter has void type, then
+ however the function cannot be defined or called, so
+ warn. */
- for (parm = last_function_parms, typelt = first_parm;
+ for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
parm;
- parm = TREE_CHAIN (parm))
- /* Skip over any enumeration constants declared here. */
- if (TREE_CODE (parm) == PARM_DECL)
- {
- /* Barf if the parameter itself has an incomplete type. */
- tree type = TREE_VALUE (typelt);
- if (type == error_mark_node)
- continue;
- if (!COMPLETE_TYPE_P (type))
- {
- if (funcdef_flag && DECL_NAME (parm) != 0)
- error ("parameter `%s' has incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (parm)));
- else
- warning ("parameter has incomplete type");
- if (funcdef_flag)
- {
- TREE_VALUE (typelt) = error_mark_node;
- TREE_TYPE (parm) = error_mark_node;
- }
- }
- typelt = TREE_CHAIN (typelt);
- }
+ parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
+ {
+ type = TREE_VALUE (typelt);
+ if (type == error_mark_node)
+ continue;
+
+ if (!COMPLETE_TYPE_P (type))
+ {
+ if (funcdef_flag)
+ {
+ if (DECL_NAME (parm))
+ error ("parameter %u (%q+D) has incomplete type",
+ parmno, parm);
+ else
+ error ("%Jparameter %u has incomplete type",
+ parm, parmno);
+
+ TREE_VALUE (typelt) = error_mark_node;
+ TREE_TYPE (parm) = error_mark_node;
+ }
+ else if (VOID_TYPE_P (type))
+ {
+ if (DECL_NAME (parm))
+ warning (0, "parameter %u (%q+D) has void type",
+ parmno, parm);
+ else
+ warning (0, "%Jparameter %u has void type",
+ parm, parmno);
+ }
+ }
- return first_parm;
+ if (DECL_NAME (parm) && TREE_USED (parm))
+ warn_if_shadowing (parm);
+ }
+ return arg_types;
}
}
-/* Return a tree_list node with info on a parameter list just parsed.
- The TREE_PURPOSE is a list of decls of those parms.
- The TREE_VALUE is a list of structure, union and enum tags defined.
- The TREE_CHAIN is a list of argument types to go in the FUNCTION_TYPE.
- The TREE_TYPE is a list of non-parameter decls which appeared with the
- parameters.
- This tree_list node is later fed to `grokparms'.
+/* Take apart the current scope and return a c_arg_info structure with
+ info on a parameter list just parsed.
- VOID_AT_END nonzero means append `void' to the end of the type-list.
- Zero means the parmlist ended with an ellipsis so don't append `void'. */
+ This structure is later fed to 'grokparms' and 'store_parm_decls'.
-tree
-get_parm_info (int void_at_end)
+ ELLIPSIS being true means the argument list ended in '...' so don't
+ append a sentinel (void_list_node) to the end of the type-list. */
+
+struct c_arg_info *
+get_parm_info (bool ellipsis)
{
- tree decl, type, list;
- tree types = 0;
- tree *last_type = &types;
- tree tags = current_scope->tags;
- tree parms = current_scope->parms;
- tree others = current_scope->names;
+ struct c_binding *b = current_scope->bindings;
+ struct c_arg_info *arg_info = XOBNEW (&parser_obstack,
+ struct c_arg_info);
+ tree parms = 0;
+ tree tags = 0;
+ tree types = 0;
+ tree others = 0;
+
static bool explained_incomplete_types = false;
bool gave_void_only_once_err = false;
- /* Just "void" (and no ellipsis) is special. There are really no parms.
- But if the "void" is qualified (by "const" or "volatile"), or has a
- storage class specifier ("register"), then the behavior is undefined;
- issue an error. Typedefs for "void" are OK (see DR#157). */
- if (void_at_end && parms != 0
- && TREE_CHAIN (parms) == 0
- && VOID_TYPE_P (TREE_TYPE (parms))
- && !DECL_NAME (parms))
- {
- if (TREE_THIS_VOLATILE (parms)
- || TREE_READONLY (parms)
- || DECL_REGISTER (parms))
- error ("\"void\" as only parameter may not be qualified");
+ arg_info->parms = 0;
+ arg_info->tags = 0;
+ arg_info->types = 0;
+ arg_info->others = 0;
+ arg_info->pending_sizes = 0;
+ arg_info->had_vla_unspec = current_scope->had_vla_unspec;
- return tree_cons (0, 0, tree_cons (0, void_type_node, 0));
- }
+ /* The bindings in this scope must not get put into a block.
+ We will take care of deleting the binding nodes. */
+ current_scope->bindings = 0;
- /* Sanity check all of the parameter declarations. */
- for (decl = parms; decl; decl = TREE_CHAIN (decl))
- {
- if (TREE_CODE (decl) != PARM_DECL)
- abort ();
- if (TREE_ASM_WRITTEN (decl))
- abort ();
+ /* This function is only called if there was *something* on the
+ parameter list. */
+ gcc_assert (b);
- /* Since there is a prototype, args are passed in their
- declared types. The back end may override this. */
- type = TREE_TYPE (decl);
- DECL_ARG_TYPE (decl) = type;
+ /* A parameter list consisting solely of 'void' indicates that the
+ function takes no arguments. But if the 'void' is qualified
+ (by 'const' or 'volatile'), or has a storage class specifier
+ ('register'), then the behavior is undefined; issue an error.
+ Typedefs for 'void' are OK (see DR#157). */
+ if (b->prev == 0 /* one binding */
+ && TREE_CODE (b->decl) == PARM_DECL /* which is a parameter */
+ && !DECL_NAME (b->decl) /* anonymous */
+ && VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */
+ {
+ if (TREE_THIS_VOLATILE (b->decl)
+ || TREE_READONLY (b->decl)
+ || C_DECL_REGISTER (b->decl))
+ error ("%<void%> as only parameter may not be qualified");
- /* Check for (..., void, ...) and issue an error. */
- if (VOID_TYPE_P (type) && !DECL_NAME (decl) && !gave_void_only_once_err)
- {
- error ("\"void\" must be the only parameter");
- gave_void_only_once_err = true;
- }
+ /* There cannot be an ellipsis. */
+ if (ellipsis)
+ error ("%<void%> must be the only parameter");
- type = build_tree_list (0, type);
- *last_type = type;
- last_type = &TREE_CHAIN (type);
+ arg_info->types = void_list_node;
+ return arg_info;
}
- /* Check the list of non-parameter decls for any forward parm decls
- that never got real decls. */
- for (decl = others; decl; decl = TREE_CHAIN (decl))
- if (TREE_CODE (decl) == PARM_DECL)
- {
- if (!TREE_ASM_WRITTEN (decl))
- abort ();
-
- error ("%Jparameter \"%D\" has just a forward declaration",
- decl, decl);
- }
+ if (!ellipsis)
+ types = void_list_node;
- /* Warn about any struct, union or enum tags defined within this
- list. The scope of such types is limited to this declaration,
- which is rarely if ever desirable (it's impossible to call such
- a function with type-correct arguments). */
- for (decl = tags; decl; decl = TREE_CHAIN (decl))
+ /* Break up the bindings list into parms, tags, types, and others;
+ apply sanity checks; purge the name-to-decl bindings. */
+ while (b)
{
- enum tree_code code = TREE_CODE (TREE_VALUE (decl));
+ tree decl = b->decl;
+ tree type = TREE_TYPE (decl);
const char *keyword;
- /* An anonymous union parm type is meaningful as a GNU extension.
- So don't warn for that. */
- if (code == UNION_TYPE && TREE_PURPOSE (decl) == 0 && !pedantic)
- continue;
- /* The keyword should not be translated. */
- switch (code)
+ switch (TREE_CODE (decl))
{
- case RECORD_TYPE: keyword = "struct"; break;
- case UNION_TYPE: keyword = "union"; break;
- case ENUMERAL_TYPE: keyword = "enum"; break;
- default: abort ();
- }
+ case PARM_DECL:
+ if (b->id)
+ {
+ gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+ I_SYMBOL_BINDING (b->id) = b->shadowed;
+ }
- if (TREE_PURPOSE (decl))
- /* The first %s will be one of 'struct', 'union', or 'enum'. */
- warning ("\"%s %s\" declared inside parameter list",
- keyword, IDENTIFIER_POINTER (TREE_PURPOSE (decl)));
- else
- /* The %s will be one of 'struct', 'union', or 'enum'. */
- warning ("anonymous %s declared inside parameter list", keyword);
+ /* Check for forward decls that never got their actual decl. */
+ if (TREE_ASM_WRITTEN (decl))
+ error ("parameter %q+D has just a forward declaration", decl);
+ /* Check for (..., void, ...) and issue an error. */
+ else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
+ {
+ if (!gave_void_only_once_err)
+ {
+ error ("%<void%> must be the only parameter");
+ gave_void_only_once_err = true;
+ }
+ }
+ else
+ {
+ /* Valid parameter, add it to the list. */
+ TREE_CHAIN (decl) = parms;
+ parms = decl;
+
+ /* Since there is a prototype, args are passed in their
+ declared types. The back end may override this later. */
+ DECL_ARG_TYPE (decl) = type;
+ types = tree_cons (0, type, types);
+ }
+ break;
- if (! explained_incomplete_types)
- {
- warning ("its scope is only this definition or declaration,"
- " which is probably not what you want");
- explained_incomplete_types = true;
- }
- }
+ case ENUMERAL_TYPE: keyword = "enum"; goto tag;
+ case UNION_TYPE: keyword = "union"; goto tag;
+ case RECORD_TYPE: keyword = "struct"; goto tag;
+ tag:
+ /* Types may not have tag-names, in which case the type
+ appears in the bindings list with b->id NULL. */
+ if (b->id)
+ {
+ gcc_assert (I_TAG_BINDING (b->id) == b);
+ I_TAG_BINDING (b->id) = b->shadowed;
+ }
+ /* Warn about any struct, union or enum tags defined in a
+ parameter list. The scope of such types is limited to
+ the parameter list, which is rarely if ever desirable
+ (it's impossible to call such a function with type-
+ correct arguments). An anonymous union parm type is
+ meaningful as a GNU extension, so don't warn for that. */
+ if (TREE_CODE (decl) != UNION_TYPE || b->id != 0)
+ {
+ if (b->id)
+ /* The %s will be one of 'struct', 'union', or 'enum'. */
+ warning (0, "%<%s %E%> declared inside parameter list",
+ keyword, b->id);
+ else
+ /* The %s will be one of 'struct', 'union', or 'enum'. */
+ warning (0, "anonymous %s declared inside parameter list",
+ keyword);
- if (void_at_end)
- {
- type = build_tree_list (0, void_type_node);
- *last_type = type;
+ if (!explained_incomplete_types)
+ {
+ warning (0, "its scope is only this definition or declaration,"
+ " which is probably not what you want");
+ explained_incomplete_types = true;
+ }
+ }
+
+ tags = tree_cons (b->id, decl, tags);
+ break;
+
+ case CONST_DECL:
+ case TYPE_DECL:
+ case FUNCTION_DECL:
+ /* CONST_DECLs appear here when we have an embedded enum,
+ and TYPE_DECLs appear here when we have an embedded struct
+ or union. No warnings for this - we already warned about the
+ type itself. FUNCTION_DECLs appear when there is an implicit
+ function declaration in the parameter list. */
+
+ TREE_CHAIN (decl) = others;
+ others = decl;
+ /* fall through */
+
+ case ERROR_MARK:
+ /* error_mark_node appears here when we have an undeclared
+ variable. Just throw it away. */
+ if (b->id)
+ {
+ gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+ I_SYMBOL_BINDING (b->id) = b->shadowed;
+ }
+ break;
+
+ /* Other things that might be encountered. */
+ case LABEL_DECL:
+ case VAR_DECL:
+ default:
+ gcc_unreachable ();
+ }
+
+ b = free_binding_and_advance (b);
}
- list = tree_cons (parms, tags, types);
- TREE_TYPE (list) = others;
- return list;
+ arg_info->parms = parms;
+ arg_info->tags = tags;
+ arg_info->types = types;
+ arg_info->others = others;
+ arg_info->pending_sizes = get_pending_sizes ();
+ return arg_info;
}
/* Get the struct, enum or union (CODE says which) with tag NAME.
- Define the tag as a forward-reference if it is not defined. */
+ Define the tag as a forward-reference if it is not defined.
+ Return a c_typespec structure for the type specifier. */
-tree
-xref_tag (enum tree_code code, tree name)
+struct c_typespec
+parser_xref_tag (enum tree_code code, tree name)
{
+ struct c_typespec ret;
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
@@ -4761,8 +5217,12 @@ xref_tag (enum tree_code code, tree name)
this would not work properly if we return the reference found.
(For example, with "struct foo" in an outer scope, "union foo;"
must shadow that tag with a new one of union type.) */
+ ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
if (ref && TREE_CODE (ref) == code)
- return ref;
+ {
+ ret.spec = ref;
+ return ret;
+ }
/* If no such tag is yet defined, create a forward-reference node
and record it as the "definition".
@@ -4777,7 +5237,7 @@ xref_tag (enum tree_code code, tree name)
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
TYPE_USER_ALIGN (ref) = 0;
- TREE_UNSIGNED (ref) = 1;
+ TYPE_UNSIGNED (ref) = 1;
TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
@@ -4785,7 +5245,18 @@ xref_tag (enum tree_code code, tree name)
pushtag (name, ref);
- return ref;
+ ret.spec = ref;
+ return ret;
+}
+
+/* Get the struct, enum or union (CODE says which) with tag NAME.
+ Define the tag as a forward-reference if it is not defined.
+ Return a tree for the type. */
+
+tree
+xref_tag (enum tree_code code, tree name)
+{
+ return parser_xref_tag (code, name).spec;
}
/* Make sure that the tag NAME is defined *in the current scope*
@@ -4805,20 +5276,18 @@ start_struct (enum tree_code code, tree name)
if (ref && TREE_CODE (ref) == code)
{
if (TYPE_SIZE (ref))
- {
+ {
if (code == UNION_TYPE)
- error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
- else
- error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
+ error ("redefinition of %<union %E%>", name);
+ else
+ error ("redefinition of %<struct %E%>", name);
}
else if (C_TYPE_BEING_DEFINED (ref))
{
if (code == UNION_TYPE)
- error ("nested redefinition of `union %s'",
- IDENTIFIER_POINTER (name));
- else
- error ("nested redefinition of `struct %s'",
- IDENTIFIER_POINTER (name));
+ error ("nested redefinition of %<union %E%>", name);
+ else
+ error ("nested redefinition of %<struct %E%>", name);
}
}
else
@@ -4834,7 +5303,7 @@ start_struct (enum tree_code code, tree name)
return ref;
}
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
+/* Process the specs, declarator and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
@@ -4843,11 +5312,13 @@ start_struct (enum tree_code code, tree name)
are ultimately passed to `build_struct' to make the RECORD_TYPE node. */
tree
-grokfield (tree declarator, tree declspecs, tree width)
+grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
+ tree width)
{
tree value;
- if (declarator == NULL_TREE && width == NULL_TREE)
+ if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
+ && width == NULL_TREE)
{
/* This is an unnamed decl.
@@ -4868,30 +5339,33 @@ grokfield (tree declarator, tree declspecs, tree width)
took this from Plan 9 or if it was an accident of implementation
that took root before someone noticed the bug... */
- tree type = TREE_VALUE (declspecs);
+ tree type = declspecs->type;
+ bool type_ok = (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE);
+ bool ok = false;
- if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
+ if (type_ok
+ && (flag_ms_extensions || !declspecs->typedef_p))
{
if (flag_ms_extensions)
- ; /* ok */
+ ok = true;
else if (flag_iso)
- goto warn_unnamed_field;
+ ok = false;
else if (TYPE_NAME (type) == NULL)
- ; /* ok */
+ ok = true;
else
- goto warn_unnamed_field;
+ ok = false;
}
- else
+ if (!ok)
{
- warn_unnamed_field:
- warning ("declaration does not declare anything");
+ pedwarn ("declaration does not declare anything");
return NULL_TREE;
}
+ if (pedantic)
+ pedwarn ("ISO C doesn%'t support unnamed structs/unions");
}
- value = grokdeclarator (declarator, declspecs, FIELD, 0,
+ value = grokdeclarator (declarator, declspecs, FIELD, false,
width ? &width : NULL);
finish_decl (value, NULL_TREE, NULL_TREE);
@@ -4931,7 +5405,7 @@ detect_field_duplicates (tree fieldlist)
for (y = fieldlist; y != x; y = TREE_CHAIN (y))
if (DECL_NAME (y) == DECL_NAME (x))
{
- error ("%Jduplicate member '%D'", x, x);
+ error ("duplicate member %q+D", x);
DECL_NAME (x) = NULL_TREE;
}
}
@@ -4947,7 +5421,7 @@ detect_field_duplicates (tree fieldlist)
slot = htab_find_slot (htab, y, INSERT);
if (*slot)
{
- error ("%Jduplicate member '%D'", x, x);
+ error ("duplicate member %q+D", x);
DECL_NAME (x) = NULL_TREE;
}
*slot = y;
@@ -4965,7 +5439,7 @@ tree
finish_struct (tree t, tree fieldlist, tree attributes)
{
tree x;
- int toplevel = global_scope == current_scope;
+ bool toplevel = file_scope == current_scope;
int saw_named_field;
/* If this type was previously laid out as a forward reference,
@@ -4975,19 +5449,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
- /* Nameless union parm types are useful as GCC extension. */
- if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
- /* Otherwise, warn about any struct or union def. in parmlist. */
- if (in_parm_level_p ())
- {
- if (pedantic)
- pedwarn ("%s defined inside parms",
- TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
- else
- warning ("%s defined inside parms",
- TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
- }
-
if (pedantic)
{
for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -4995,21 +5456,41 @@ finish_struct (tree t, tree fieldlist, tree attributes)
break;
if (x == 0)
- pedwarn ("%s has no %s",
- TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
- fieldlist ? _("named members") : _("members"));
+ {
+ if (TREE_CODE (t) == UNION_TYPE)
+ {
+ if (fieldlist)
+ pedwarn ("union has no named members");
+ else
+ pedwarn ("union has no members");
+ }
+ else
+ {
+ if (fieldlist)
+ pedwarn ("struct has no named members");
+ else
+ pedwarn ("struct has no members");
+ }
+ }
}
/* Install struct as DECL_CONTEXT of each field decl.
- Also process specified field sizes,m which is found in the DECL_INITIAL.
- Store 0 there, except for ": 0" fields (so we can find them
- and delete them, below). */
+ Also process specified field sizes, found in the DECL_INITIAL,
+ storing 0 there after the type has been changed to precision equal
+ to its width, rather than the precision of the specified standard
+ type. (Correct layout requires the original type to have been preserved
+ until now.) */
saw_named_field = 0;
for (x = fieldlist; x; x = TREE_CHAIN (x))
{
+ if (TREE_TYPE (x) == error_mark_node)
+ continue;
+
DECL_CONTEXT (x) = t;
- DECL_PACKED (x) |= TYPE_PACKED (t);
+
+ if (TYPE_PACKED (t) && TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
+ DECL_PACKED (x) = 1;
/* If any field is const, the structure type is pseudo-const. */
if (TREE_READONLY (x))
@@ -5042,8 +5523,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
SET_DECL_C_BIT_FIELD (x);
}
- DECL_INITIAL (x) = 0;
-
/* Detect flexible array member in an invalid context. */
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
@@ -5060,7 +5539,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
error ("%Jflexible array member not at end of struct", x);
TREE_TYPE (x) = error_mark_node;
}
- else if (! saw_named_field)
+ else if (!saw_named_field)
{
error ("%Jflexible array member in otherwise empty struct", x);
TREE_TYPE (x) = error_mark_node;
@@ -5084,12 +5563,24 @@ finish_struct (tree t, tree fieldlist, tree attributes)
layout_type (t);
- /* Delete all zero-width bit-fields from the fieldlist. */
+ /* Give bit-fields their proper types. */
{
tree *fieldlistp = &fieldlist;
while (*fieldlistp)
- if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
- *fieldlistp = TREE_CHAIN (*fieldlistp);
+ if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
+ && TREE_TYPE (*fieldlistp) != error_mark_node)
+ {
+ unsigned HOST_WIDE_INT width
+ = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
+ tree type = TREE_TYPE (*fieldlistp);
+ if (width != TYPE_PRECISION (type))
+ {
+ TREE_TYPE (*fieldlistp)
+ = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
+ DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
+ }
+ DECL_INITIAL (*fieldlistp) = 0;
+ }
else
fieldlistp = &TREE_CHAIN (*fieldlistp);
}
@@ -5107,45 +5598,46 @@ finish_struct (tree t, tree fieldlist, tree attributes)
for (x = fieldlist; x; x = TREE_CHAIN (x))
{
- if (len > 15 || DECL_NAME (x) == NULL)
- break;
- len += 1;
+ if (len > 15 || DECL_NAME (x) == NULL)
+ break;
+ len += 1;
}
if (len > 15)
{
- tree *field_array;
- struct lang_type *space;
- struct sorted_fields_type *space2;
+ tree *field_array;
+ struct lang_type *space;
+ struct sorted_fields_type *space2;
- len += list_length (x);
+ len += list_length (x);
- /* Use the same allocation policy here that make_node uses, to
- ensure that this lives as long as the rest of the struct decl.
- All decls in an inline function need to be saved. */
+ /* Use the same allocation policy here that make_node uses, to
+ ensure that this lives as long as the rest of the struct decl.
+ All decls in an inline function need to be saved. */
- space = ggc_alloc (sizeof (struct lang_type));
- space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+ space = GGC_CNEW (struct lang_type);
+ space2 = GGC_NEWVAR (struct sorted_fields_type,
+ sizeof (struct sorted_fields_type) + len * sizeof (tree));
- len = 0;
+ len = 0;
space->s = space2;
field_array = &space2->elts[0];
- for (x = fieldlist; x; x = TREE_CHAIN (x))
- {
- field_array[len++] = x;
-
- /* If there is anonymous struct or union, break out of the loop. */
- if (DECL_NAME (x) == NULL)
- break;
- }
- /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */
- if (x == NULL)
- {
- TYPE_LANG_SPECIFIC (t) = space;
- TYPE_LANG_SPECIFIC (t)->s->len = len;
- field_array = TYPE_LANG_SPECIFIC (t)->s->elts;
- qsort (field_array, len, sizeof (tree), field_decl_cmp);
- }
+ for (x = fieldlist; x; x = TREE_CHAIN (x))
+ {
+ field_array[len++] = x;
+
+ /* If there is anonymous struct or union, break out of the loop. */
+ if (DECL_NAME (x) == NULL)
+ break;
+ }
+ /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */
+ if (x == NULL)
+ {
+ TYPE_LANG_SPECIFIC (t) = space;
+ TYPE_LANG_SPECIFIC (t)->s->len = len;
+ field_array = TYPE_LANG_SPECIFIC (t)->s->elts;
+ qsort (field_array, len, sizeof (tree), field_decl_cmp);
+ }
}
}
@@ -5153,8 +5645,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
{
TYPE_FIELDS (x) = TYPE_FIELDS (t);
TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
- TYPE_ALIGN (x) = TYPE_ALIGN (t);
- TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t);
C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
@@ -5167,7 +5657,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
&& (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))))
{
TYPE_TRANSPARENT_UNION (t) = 0;
- warning ("union cannot be made transparent");
+ warning (0, "union cannot be made transparent");
}
/* If this structure or union completes the type of any previous
@@ -5184,8 +5674,8 @@ finish_struct (tree t, tree fieldlist, tree attributes)
layout_decl (decl, 0);
if (c_dialect_objc ())
objc_check_decl (decl);
- rest_of_decl_compilation (decl, NULL, toplevel, 0);
- if (! toplevel)
+ rest_of_decl_compilation (decl, toplevel, 0);
+ if (!toplevel)
expand_decl (decl);
}
}
@@ -5194,6 +5684,12 @@ finish_struct (tree t, tree fieldlist, tree attributes)
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel);
+ /* If we're inside a function proper, i.e. not file-scope and not still
+ parsing parameters, then arrange for the size of a variable sized type
+ to be bound now. */
+ if (cur_stmt_list && variably_modified_type_p (t, NULL_TREE))
+ add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t)));
+
return t;
}
@@ -5232,14 +5728,14 @@ start_enum (tree name)
}
if (C_TYPE_BEING_DEFINED (enumtype))
- error ("nested redefinition of `enum %s'", IDENTIFIER_POINTER (name));
+ error ("nested redefinition of %<enum %E%>", name);
C_TYPE_BEING_DEFINED (enumtype) = 1;
if (TYPE_VALUES (enumtype) != 0)
{
/* This enum is a named one that has been declared already. */
- error ("redeclaration of `enum %s'", IDENTIFIER_POINTER (name));
+ error ("redeclaration of %<enum %E%>", name);
/* Completely replace its old definition.
The old enumerators remain defined, however. */
@@ -5265,12 +5761,10 @@ tree
finish_enum (tree enumtype, tree values, tree attributes)
{
tree pair, tem;
- tree minnode = 0, maxnode = 0, enum_value_type;
+ tree minnode = 0, maxnode = 0;
int precision, unsign;
- int toplevel = (global_scope == current_scope);
-
- if (in_parm_level_p ())
- warning ("enum defined inside parms");
+ bool toplevel = (file_scope == current_scope);
+ struct lang_type *lt;
decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
@@ -5298,28 +5792,22 @@ finish_enum (tree enumtype, tree values, tree attributes)
unsign = (tree_int_cst_sgn (minnode) >= 0);
precision = MAX (min_precision (minnode, unsign),
min_precision (maxnode, unsign));
+
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
- tree narrowest = c_common_type_for_size (precision, unsign);
- if (narrowest == 0)
+ tem = c_common_type_for_size (precision, unsign);
+ if (tem == NULL)
{
- warning ("enumeration values exceed range of largest integer");
- narrowest = long_long_integer_type_node;
+ warning (0, "enumeration values exceed range of largest integer");
+ tem = long_long_integer_type_node;
}
-
- precision = TYPE_PRECISION (narrowest);
}
else
- precision = TYPE_PRECISION (integer_type_node);
+ tem = unsign ? unsigned_type_node : integer_type_node;
- if (precision == TYPE_PRECISION (integer_type_node))
- enum_value_type = c_common_type_for_size (precision, 0);
- else
- enum_value_type = enumtype;
-
- TYPE_MIN_VALUE (enumtype) = minnode;
- TYPE_MAX_VALUE (enumtype) = maxnode;
- TREE_UNSIGNED (enumtype) = unsign;
+ TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
+ TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
+ TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
TYPE_SIZE (enumtype) = 0;
/* If the precision of the type was specific with an attribute and it
@@ -5330,7 +5818,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
error ("specified mode too small for enumeral values");
}
else
- TYPE_PRECISION (enumtype) = precision;
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
layout_type (enumtype);
@@ -5346,6 +5834,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
for (pair = values; pair; pair = TREE_CHAIN (pair))
{
tree enu = TREE_PURPOSE (pair);
+ tree ini = DECL_INITIAL (enu);
TREE_TYPE (enu) = enumtype;
@@ -5356,18 +5845,27 @@ finish_enum (tree enumtype, tree values, tree attributes)
when comparing integers with enumerators that fit in the
int range. When -pedantic is given, build_enumerator()
would have already taken care of those that don't fit. */
- if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
- DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
+ if (int_fits_type_p (ini, integer_type_node))
+ tem = integer_type_node;
else
- DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
+ tem = enumtype;
+ ini = convert (tem, ini);
+ DECL_INITIAL (enu) = ini;
TREE_PURPOSE (pair) = DECL_NAME (enu);
- TREE_VALUE (pair) = DECL_INITIAL (enu);
+ TREE_VALUE (pair) = ini;
}
TYPE_VALUES (enumtype) = values;
}
+ /* Record the min/max values so that we can warn about bit-field
+ enumerations that are too small for the values. */
+ lt = GGC_CNEW (struct lang_type);
+ lt->enum_min = minnode;
+ lt->enum_max = maxnode;
+ TYPE_LANG_SPECIFIC (enumtype) = lt;
+
/* Fix up all variant types of this enum type. */
for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
{
@@ -5382,7 +5880,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
- TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+ TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
+ TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
}
/* Finish debugging output for this type. */
@@ -5403,22 +5902,22 @@ build_enumerator (tree name, tree value)
/* Validate and default VALUE. */
- /* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-
if (value != 0)
{
- if (TREE_CODE (value) == INTEGER_CST)
+ /* Don't issue more errors for error_mark_node (i.e. an
+ undeclared identifier) - just ignore the value expression. */
+ if (value == error_mark_node)
+ value = 0;
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
+ || TREE_CODE (value) != INTEGER_CST)
{
- value = default_conversion (value);
- constant_expression_warning (value);
+ error ("enumerator value for %qE is not an integer constant", name);
+ value = 0;
}
else
{
- error ("enumerator value for `%s' not integer constant",
- IDENTIFIER_POINTER (name));
- value = 0;
+ value = default_conversion (value);
+ constant_expression_warning (value);
}
}
@@ -5432,9 +5931,11 @@ build_enumerator (tree name, tree value)
error ("overflow in enumeration values");
}
- if (pedantic && ! int_fits_type_p (value, integer_type_node))
+ if (pedantic && !int_fits_type_p (value, integer_type_node))
{
- pedwarn ("ISO C restricts enumerator values to range of `int'");
+ pedwarn ("ISO C restricts enumerator values to range of %<int%>");
+ /* XXX This causes -pedantic to change the meaning of the program.
+ Remove? -zw 2004-03-15 */
value = convert (integer_type_node, value);
}
@@ -5449,7 +5950,7 @@ build_enumerator (tree name, tree value)
TYPE_PRECISION (integer_type_node)),
(TYPE_PRECISION (type)
>= TYPE_PRECISION (integer_type_node)
- && TREE_UNSIGNED (type)));
+ && TYPE_UNSIGNED (type)));
decl = build_decl (CONST_DECL, name, type);
DECL_INITIAL (decl) = convert (type, value);
@@ -5472,30 +5973,47 @@ build_enumerator (tree name, tree value)
yyparse to report a parse error. */
int
-start_function (tree declspecs, tree declarator, tree attributes)
+start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
+ tree attributes)
{
tree decl1, old_decl;
- tree restype;
- int old_immediate_size_expand = immediate_size_expand;
+ tree restype, resdecl;
+ struct c_label_context_se *nstack_se;
+ struct c_label_context_vm *nstack_vm;
current_function_returns_value = 0; /* Assume, until we see it does. */
current_function_returns_null = 0;
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
- c_in_iteration_stmt = 0;
- c_in_case_stmt = 0;
+ c_switch_stack = NULL;
+
+ nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se);
+ nstack_se->labels_def = NULL;
+ nstack_se->labels_used = NULL;
+ nstack_se->next = label_context_stack_se;
+ label_context_stack_se = nstack_se;
+
+ nstack_vm = XOBNEW (&parser_obstack, struct c_label_context_vm);
+ nstack_vm->labels_def = NULL;
+ nstack_vm->labels_used = NULL;
+ nstack_vm->scope = 0;
+ nstack_vm->next = label_context_stack_vm;
+ label_context_stack_vm = nstack_vm;
- /* Don't expand any sizes in the return type of the function. */
- immediate_size_expand = 0;
+ /* Indicate no valid break/continue context by setting these variables
+ to some non-null, non-label value. We'll notice and emit the proper
+ error message in c_finish_bc_stmt. */
+ c_break_label = c_cont_label = size_zero_node;
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == 0)
{
- immediate_size_expand = old_immediate_size_expand;
+ label_context_stack_se = label_context_stack_se->next;
+ label_context_stack_vm = label_context_stack_vm->next;
return 0;
}
@@ -5504,7 +6022,8 @@ start_function (tree declspecs, tree declarator, tree attributes)
if (DECL_DECLARED_INLINE_P (decl1)
&& DECL_UNINLINABLE (decl1)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
- warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
+ warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
+ decl1);
announce_function (decl1);
@@ -5518,63 +6037,105 @@ start_function (tree declspecs, tree declarator, tree attributes)
}
if (warn_about_return_type)
- pedwarn_c99 ("return type defaults to `int'");
-
- /* Save the parm names or decls from this function's declarator
- where store_parm_decls will find them. */
- current_function_parms = last_function_parms;
- current_function_parm_tags = last_function_parm_tags;
- current_function_parm_others = last_function_parm_others;
+ pedwarn_c99 ("return type defaults to %<int%>");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
- error_mark_node is replaced below (in poplevel) with the BLOCK. */
+ error_mark_node is replaced below (in pop_scope) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
/* If this definition isn't a prototype and we had a prototype declaration
- before, copy the arg type info from that prototype.
- But not if what we had before was a builtin function. */
- old_decl = lookup_name_current_level (DECL_NAME (decl1));
- if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
- && !DECL_BUILT_IN (old_decl)
- && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
- == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (old_decl))))
- && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
- {
- TREE_TYPE (decl1) = TREE_TYPE (old_decl);
- current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
+ before, copy the arg type info from that prototype. */
+ old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
+ if (old_decl && TREE_CODE (old_decl) != FUNCTION_DECL)
+ old_decl = 0;
+ current_function_prototype_locus = UNKNOWN_LOCATION;
+ current_function_prototype_built_in = false;
+ current_function_prototype_arg_types = NULL_TREE;
+ if (TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
+ {
+ if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
+ && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+ TREE_TYPE (TREE_TYPE (old_decl))))
+ {
+ TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
+ TREE_TYPE (decl1));
+ current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
+ current_function_prototype_built_in
+ = C_DECL_BUILTIN_PROTOTYPE (old_decl);
+ current_function_prototype_arg_types
+ = TYPE_ARG_TYPES (TREE_TYPE (decl1));
+ }
+ if (TREE_PUBLIC (decl1))
+ {
+ /* If there is an external prototype declaration of this
+ function, record its location but do not copy information
+ to this decl. This may be an invisible declaration
+ (built-in or in a scope which has finished) or simply
+ have more refined argument types than any declaration
+ found above. */
+ struct c_binding *b;
+ for (b = I_SYMBOL_BINDING (DECL_NAME (decl1)); b; b = b->shadowed)
+ if (B_IN_SCOPE (b, external_scope))
+ break;
+ if (b)
+ {
+ tree ext_decl, ext_type;
+ ext_decl = b->decl;
+ ext_type = b->type ? b->type : TREE_TYPE (ext_decl);
+ if (TREE_CODE (ext_type) == FUNCTION_TYPE
+ && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+ TREE_TYPE (ext_type)))
+ {
+ current_function_prototype_locus
+ = DECL_SOURCE_LOCATION (ext_decl);
+ current_function_prototype_built_in
+ = C_DECL_BUILTIN_PROTOTYPE (ext_decl);
+ current_function_prototype_arg_types
+ = TYPE_ARG_TYPES (ext_type);
+ }
+ }
+ }
}
/* Optionally warn of old-fashioned def with no previous prototype. */
if (warn_strict_prototypes
+ && old_decl != error_mark_node
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
&& C_DECL_ISNT_PROTOTYPE (old_decl))
- warning ("function declaration isn't a prototype");
+ warning (OPT_Wstrict_prototypes,
+ "function declaration isn%'t a prototype");
/* Optionally warn of any global def with no previous prototype. */
else if (warn_missing_prototypes
+ && old_decl != error_mark_node
&& TREE_PUBLIC (decl1)
- && ! MAIN_NAME_P (DECL_NAME (decl1))
+ && !MAIN_NAME_P (DECL_NAME (decl1))
&& C_DECL_ISNT_PROTOTYPE (old_decl))
- warning ("%Jno previous prototype for '%D'", decl1, decl1);
+ warning (OPT_Wmissing_prototypes, "no previous prototype for %q+D", decl1);
/* Optionally warn of any def with no previous prototype
if the function has already been used. */
else if (warn_missing_prototypes
- && old_decl != 0 && TREE_USED (old_decl)
+ && old_decl != 0
+ && old_decl != error_mark_node
+ && TREE_USED (old_decl)
&& TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
- warning ("%J'%D' was used with no prototype before its definition",
- decl1, decl1);
+ warning (OPT_Wmissing_prototypes,
+ "%q+D was used with no prototype before its definition", decl1);
/* Optionally warn of any global def with no previous declaration. */
else if (warn_missing_declarations
&& TREE_PUBLIC (decl1)
&& old_decl == 0
- && ! MAIN_NAME_P (DECL_NAME (decl1)))
- warning ("%Jno previous declaration for '%D'", decl1, decl1);
+ && !MAIN_NAME_P (DECL_NAME (decl1)))
+ warning (OPT_Wmissing_declarations, "no previous declaration for %q+D",
+ decl1);
/* Optionally warn of any def with no previous declaration
if the function has already been used. */
else if (warn_missing_declarations
- && old_decl != 0 && TREE_USED (old_decl)
+ && old_decl != 0
+ && old_decl != error_mark_node
+ && TREE_USED (old_decl)
&& C_DECL_IMPLICIT (old_decl))
- warning ("%J`%D' was used with no declaration before its definition",
- decl1, decl1);
+ warning (OPT_Wmissing_declarations,
+ "%q+D was used with no declaration before its definition", decl1);
/* This is a definition, not a reference.
So normally clear DECL_EXTERNAL.
@@ -5582,6 +6143,30 @@ start_function (tree declspecs, tree declarator, tree attributes)
except for defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
+ /* C99 specified different behaviour for non-static inline
+ functions, compared with the traditional GNU behaviour. We don't
+ support the C99 behaviour, but we do warn about non-static inline
+ functions here. The warning can be disabled via an explicit use
+ of -fgnu89-inline, or by using the gnu_inline attribute. */
+ if (DECL_DECLARED_INLINE_P (decl1)
+ && TREE_PUBLIC (decl1)
+ && flag_isoc99
+ && flag_gnu89_inline != 1
+ && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1))
+ && diagnostic_report_warnings_p ())
+ {
+ static bool info = false;
+
+ warning (0, "C99 inline functions are not supported; using GNU89");
+ if (!info)
+ {
+ warning (0,
+ "to disable this warning use -fgnu89-inline or "
+ "the gnu_inline function attribute");
+ info = true;
+ }
+ }
+
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
@@ -5590,15 +6175,12 @@ start_function (tree declspecs, tree declarator, tree attributes)
if (current_function_decl != 0)
TREE_PUBLIC (decl1) = 0;
-#ifdef ENABLE_CHECKING
/* This is the earliest point at which we might know the assembler
name of the function. Thus, if it's set before this, die horribly. */
- if (DECL_ASSEMBLER_NAME_SET_P (decl1))
- abort ();
-#endif
+ gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
/* If #pragma weak was used, mark the decl weak now. */
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
maybe_apply_pragma_weak (decl1);
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
@@ -5609,7 +6191,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
!= integer_type_node)
- pedwarn ("%Jreturn type of '%D' is not `int'", decl1, decl1);
+ pedwarn ("return type of %q+D is not %<int%>", decl1);
for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
args = TREE_CHAIN (args))
@@ -5624,8 +6206,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
{
case 1:
if (TYPE_MAIN_VARIANT (type) != integer_type_node)
- pedwarn ("%Jfirst argument of '%D' should be `int'",
- decl1, decl1);
+ pedwarn ("first argument of %q+D should be %<int%>", decl1);
break;
case 2:
@@ -5633,8 +6214,8 @@ start_function (tree declspecs, tree declarator, tree attributes)
|| TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
- pedwarn ("%Jsecond argument of '%D' should be 'char **'",
- decl1, decl1);
+ pedwarn ("second argument of %q+D should be %<char **%>",
+ decl1);
break;
case 3:
@@ -5642,8 +6223,8 @@ start_function (tree declspecs, tree declarator, tree attributes)
|| TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
- pedwarn ("%Jthird argument of '%D' should probably be "
- "'char **'", decl1, decl1);
+ pedwarn ("third argument of %q+D should probably be "
+ "%<char **%>", decl1);
break;
}
}
@@ -5652,10 +6233,10 @@ start_function (tree declspecs, tree declarator, tree attributes)
argument because it's only mentioned in an appendix of the
standard. */
if (argct > 0 && (argct < 2 || argct > 3))
- pedwarn ("%J'%D' takes only zero or two arguments", decl1, decl1);
+ pedwarn ("%q+D takes only zero or two arguments", decl1);
- if (! TREE_PUBLIC (decl1))
- pedwarn ("%J'%D' is normally a non-static function", decl1, decl1);
+ if (!TREE_PUBLIC (decl1))
+ pedwarn ("%q+D is normally a non-static function", decl1);
}
/* Record the decl so that the function name is defined.
@@ -5664,32 +6245,26 @@ start_function (tree declspecs, tree declarator, tree attributes)
current_function_decl = pushdecl (decl1);
- pushlevel (0);
+ push_scope ();
declare_parm_level ();
- make_decl_rtl (current_function_decl, NULL);
-
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
{
/* It retains unsignedness if not really getting wider. */
- if (TREE_UNSIGNED (restype)
+ if (TYPE_UNSIGNED (restype)
&& (TYPE_PRECISION (restype)
== TYPE_PRECISION (integer_type_node)))
restype = unsigned_type_node;
else
restype = integer_type_node;
}
- DECL_RESULT (current_function_decl)
- = build_decl (RESULT_DECL, NULL_TREE, restype);
- /* If this fcn was already referenced via a block-scope `extern' decl
- (or an implicit decl), propagate certain information about the usage. */
- if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
- TREE_ADDRESSABLE (current_function_decl) = 1;
-
- immediate_size_expand = old_immediate_size_expand;
+ resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
+ DECL_ARTIFICIAL (resdecl) = 1;
+ DECL_IGNORED_P (resdecl) = 1;
+ DECL_RESULT (current_function_decl) = resdecl;
start_fname_decls ();
@@ -5701,98 +6276,78 @@ start_function (tree declspecs, tree declarator, tree attributes)
need only record them as in effect and complain if any redundant
old-style parm decls were written. */
static void
-store_parm_decls_newstyle (void)
+store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
{
- tree decl, last;
- tree fndecl = current_function_decl;
- tree parms = current_function_parms;
- tree tags = current_function_parm_tags;
- tree others = current_function_parm_others;
+ tree decl;
- if (current_scope->parms || current_scope->names || current_scope->tags)
+ if (current_scope->bindings)
{
error ("%Jold-style parameter declarations in prototyped "
"function definition", fndecl);
/* Get rid of the old-style declarations. */
- poplevel (0, 0, 0);
- pushlevel (0);
- }
+ pop_scope ();
+ push_scope ();
+ }
+ /* Don't issue this warning for nested functions, and don't issue this
+ warning if we got here because ARG_INFO_TYPES was error_mark_node
+ (this happens when a function definition has just an ellipsis in
+ its parameter list). */
+ else if (!in_system_header && !current_function_scope
+ && arg_info->types != error_mark_node)
+ warning (OPT_Wtraditional,
+ "%Jtraditional C rejects ISO C style function definitions",
+ fndecl);
/* Now make all the parameter declarations visible in the function body.
We can bypass most of the grunt work of pushdecl. */
- for (last = 0, decl = parms; decl; last = decl, decl = TREE_CHAIN (decl))
+ for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
- if (DECL_NAME (decl) == 0)
- error ("%Jparameter name omitted", decl);
- else
+ if (DECL_NAME (decl))
{
- if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)))
- current_scope->shadowed
- = tree_cons (DECL_NAME (decl),
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)),
- current_scope->shadowed);
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
+ bind (DECL_NAME (decl), decl, current_scope,
+ /*invisible=*/false, /*nested=*/false);
+ if (!TREE_USED (decl))
+ warn_if_shadowing (decl);
}
+ else
+ error ("%Jparameter name omitted", decl);
}
- current_scope->parms = parms;
- current_scope->parms_last = last;
/* Record the parameter list in the function declaration. */
- DECL_ARGUMENTS (fndecl) = parms;
+ DECL_ARGUMENTS (fndecl) = arg_info->parms;
/* Now make all the ancillary declarations visible, likewise. */
- for (last = 0, decl = others; decl; last = decl, decl = TREE_CHAIN (decl))
+ for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
- if (DECL_NAME (decl)
- && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node)
- {
- if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)))
- current_scope->shadowed
- = tree_cons (DECL_NAME (decl),
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)),
- current_scope->shadowed);
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
- }
+ if (DECL_NAME (decl))
+ bind (DECL_NAME (decl), decl, current_scope,
+ /*invisible=*/false, /*nested=*/false);
}
- current_scope->names = others;
- current_scope->names_last = last;
/* And all the tag declarations. */
- for (decl = tags; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
if (TREE_PURPOSE (decl))
- {
- if (IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)))
- current_scope->shadowed_tags
- = tree_cons (TREE_PURPOSE (decl),
- IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (decl)),
- current_scope->shadowed_tags);
- IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)) = TREE_VALUE (decl);
- }
- current_scope->tags = tags;
+ bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
+ /*invisible=*/false, /*nested=*/false);
}
/* Subroutine of store_parm_decls which handles old-style function
definitions (separate parameter list and declarations). */
static void
-store_parm_decls_oldstyle (void)
+store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
{
+ struct c_binding *b;
tree parm, decl, last;
- tree fndecl = current_function_decl;
-
- /* This is the identifier list from the function declarator. */
- tree parmids = current_function_parms;
+ tree parmids = arg_info->parms;
+ struct pointer_set_t *seen_args = pointer_set_create ();
- /* We use DECL_WEAK as a flag to show which parameters have been
- seen already, since it is not used on PARM_DECL. */
-#ifdef ENABLE_CHECKING
- for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
- if (DECL_WEAK (parm))
- abort ();
-#endif
+ if (!in_system_header)
+ warning (OPT_Wold_style_definition, "%Jold-style function definition",
+ fndecl);
/* Match each formal parameter name with its declaration. Save each
decl in the appropriate TREE_PURPOSE slot of the parmids chain. */
@@ -5805,17 +6360,18 @@ store_parm_decls_oldstyle (void)
continue;
}
- decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm));
- if (decl && DECL_CONTEXT (decl) == fndecl)
+ b = I_SYMBOL_BINDING (TREE_VALUE (parm));
+ if (b && B_IN_CURRENT_SCOPE (b))
{
+ decl = b->decl;
/* If we got something other than a PARM_DECL it is an error. */
if (TREE_CODE (decl) != PARM_DECL)
- error ("%J\"%D\" declared as a non-parameter", decl, decl);
+ error ("%q+D declared as a non-parameter", decl);
/* If the declaration is already marked, we have a duplicate
name. Complain and ignore the duplicate. */
- else if (DECL_WEAK (decl))
+ else if (pointer_set_contains (seen_args, decl))
{
- error ("%Jmultiple parameters named \"%D\"", decl, decl);
+ error ("multiple parameters named %q+D", decl);
TREE_PURPOSE (parm) = 0;
continue;
}
@@ -5823,11 +6379,12 @@ store_parm_decls_oldstyle (void)
an int. */
else if (VOID_TYPE_P (TREE_TYPE (decl)))
{
- error ("%Jparameter \"%D\" declared void", decl, decl);
+ error ("parameter %q+D declared with void type", decl);
TREE_TYPE (decl) = integer_type_node;
DECL_ARG_TYPE (decl) = integer_type_node;
layout_decl (decl, 0);
}
+ warn_if_shadowing (decl);
}
/* If no declaration found, default to int. */
else
@@ -5836,32 +6393,37 @@ store_parm_decls_oldstyle (void)
DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (fndecl);
pushdecl (decl);
+ warn_if_shadowing (decl);
if (flag_isoc99)
- pedwarn ("%Jtype of \"%D\" defaults to \"int\"", decl, decl);
+ pedwarn ("type of %q+D defaults to %<int%>", decl);
else if (extra_warnings)
- warning ("%Jtype of \"%D\" defaults to \"int\"", decl, decl);
+ warning (OPT_Wextra, "type of %q+D defaults to %<int%>", decl);
}
TREE_PURPOSE (parm) = decl;
- DECL_WEAK (decl) = 1;
+ pointer_set_insert (seen_args, decl);
}
/* Now examine the parms chain for incomplete declarations
and declarations with no corresponding names. */
- for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
+ for (b = current_scope->bindings; b; b = b->prev)
{
- if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
+ parm = b->decl;
+ if (TREE_CODE (parm) != PARM_DECL)
+ continue;
+
+ if (TREE_TYPE (parm) != error_mark_node
+ && !COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
- error ("%Jparameter \"%D\" has incomplete type", parm, parm);
+ error ("parameter %q+D has incomplete type", parm);
TREE_TYPE (parm) = error_mark_node;
}
- if (! DECL_WEAK (parm))
+ if (!pointer_set_contains (seen_args, parm))
{
- error ("%Jdeclaration for parameter \"%D\" but no such parameter",
- parm, parm);
+ error ("declaration for parameter %q+D but no such parameter", parm);
/* Pretend the parameter was not missing.
This gets us to a standard state and minimizes
@@ -5882,29 +6444,27 @@ store_parm_decls_oldstyle (void)
{
last = TREE_PURPOSE (parm);
DECL_ARGUMENTS (fndecl) = last;
- current_scope->parms = last;
- DECL_WEAK (last) = 0;
for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
if (TREE_PURPOSE (parm))
{
TREE_CHAIN (last) = TREE_PURPOSE (parm);
last = TREE_PURPOSE (parm);
- DECL_WEAK (last) = 0;
}
- current_scope->parms_last = last;
TREE_CHAIN (last) = 0;
}
+ pointer_set_destroy (seen_args);
+
/* If there was a previous prototype,
set the DECL_ARG_TYPE of each argument according to
the type previously specified, and report any mismatches. */
- if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+ if (current_function_prototype_arg_types)
{
tree type;
for (parm = DECL_ARGUMENTS (fndecl),
- type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ type = current_function_prototype_arg_types;
parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
!= void_type_node));
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
@@ -5912,17 +6472,22 @@ store_parm_decls_oldstyle (void)
if (parm == 0 || type == 0
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
- error ("number of arguments doesn't match prototype");
- error ("%Hprototype declaration",
- &current_function_prototype_locus);
+ if (current_function_prototype_built_in)
+ warning (0, "number of arguments doesn%'t match "
+ "built-in prototype");
+ else
+ {
+ error ("number of arguments doesn%'t match prototype");
+ error ("%Hprototype declaration",
+ &current_function_prototype_locus);
+ }
break;
}
/* Type for passing arg must be consistent with that
declared for the arg. ISO C says we take the unqualified
type for parameters declared with qualified type. */
- if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
- TYPE_MAIN_VARIANT (TREE_VALUE (type)),
- COMPARE_STRICT))
+ if (!comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
@@ -5942,17 +6507,33 @@ store_parm_decls_oldstyle (void)
if (pedantic)
{
- pedwarn ("promoted argument \"%D\" "
- "doesn't match prototype", parm);
- pedwarn ("%Hprototype declaration",
- &current_function_prototype_locus);
+ /* ??? Is it possible to get here with a
+ built-in prototype or will it always have
+ been diagnosed as conflicting with an
+ old-style definition and discarded? */
+ if (current_function_prototype_built_in)
+ warning (0, "promoted argument %qD "
+ "doesn%'t match built-in prototype", parm);
+ else
+ {
+ pedwarn ("promoted argument %qD "
+ "doesn%'t match prototype", parm);
+ pedwarn ("%Hprototype declaration",
+ &current_function_prototype_locus);
+ }
}
}
else
{
- error ("argument \"%D\" doesn't match prototype", parm);
- error ("%Hprototype declaration",
- &current_function_prototype_locus);
+ if (current_function_prototype_built_in)
+ warning (0, "argument %qD doesn%'t match "
+ "built-in prototype", parm);
+ else
+ {
+ error ("argument %qD doesn%'t match prototype", parm);
+ error ("%Hprototype declaration",
+ &current_function_prototype_locus);
+ }
}
}
}
@@ -5988,12 +6569,22 @@ store_parm_decls_oldstyle (void)
will be a variant of the main variant of the original function
type. */
- TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
+ TREE_TYPE (fndecl) = build_variant_type_copy (TREE_TYPE (fndecl));
TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
}
}
+/* Store parameter declarations passed in ARG_INFO into the current
+ function declaration. */
+
+void
+store_parm_decls_from (struct c_arg_info *arg_info)
+{
+ current_function_arg_info = arg_info;
+ store_parm_decls ();
+}
+
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
digesting the body of the function.
@@ -6005,46 +6596,79 @@ void
store_parm_decls (void)
{
tree fndecl = current_function_decl;
+ bool proto;
+
+ /* The argument information block for FNDECL. */
+ struct c_arg_info *arg_info = current_function_arg_info;
+ current_function_arg_info = 0;
- /* True if this definition is written with a prototype. */
- bool prototype = (current_function_parms
- && TREE_CODE (current_function_parms) != TREE_LIST);
+ /* True if this definition is written with a prototype. Note:
+ despite C99 6.7.5.3p14, we can *not* treat an empty argument
+ list in a function definition as equivalent to (void) -- an
+ empty argument list specifies the function has no parameters,
+ but only (void) sets up a prototype for future calls. */
+ proto = arg_info->types != 0;
- if (prototype)
- store_parm_decls_newstyle ();
+ if (proto)
+ store_parm_decls_newstyle (fndecl, arg_info);
else
- store_parm_decls_oldstyle ();
+ store_parm_decls_oldstyle (fndecl, arg_info);
- /* The next call to pushlevel will be a function body. */
+ /* The next call to push_scope will be a function body. */
next_is_function_body = true;
/* Write a record describing this function definition to the prototypes
file (if requested). */
- gen_aux_info_record (fndecl, 1, 0, prototype);
+ gen_aux_info_record (fndecl, 1, 0, proto);
/* Initialize the RTL code for the function. */
allocate_struct_function (fndecl);
/* Begin the statement tree for this function. */
- begin_stmt_tree (&DECL_SAVED_TREE (fndecl));
-
- /* Save away the sizes of any variable-size types so that we can
- expand them when generating RTL. */
- DECL_LANG_SPECIFIC (fndecl)->pending_sizes = get_pending_sizes ();
-
- /* This function is being processed in whole-function mode. */
- cfun->x_whole_function_mode_p = 1;
+ DECL_SAVED_TREE (fndecl) = push_stmt_list ();
+
+ /* ??? Insert the contents of the pending sizes list into the function
+ to be evaluated. The only reason left to have this is
+ void foo(int n, int array[n++])
+ because we throw away the array type in favor of a pointer type, and
+ thus won't naturally see the SAVE_EXPR containing the increment. All
+ other pending sizes would be handled by gimplify_parameters. */
+ {
+ tree t;
+ for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
+ add_stmt (TREE_VALUE (t));
+ }
/* Even though we're inside a function body, we still don't want to
call expand_expr to calculate the size of a variable-sized array.
We haven't necessarily assigned RTL to all variables yet, so it's
not safe to try to expand expressions involving them. */
- immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
}
+/* Emit diagnostics that require gimple input for detection. Operate on
+ FNDECL and all its nested functions. */
+
+static void
+c_gimple_diagnostics_recursively (tree fndecl)
+{
+ struct cgraph_node *cgn;
+
+ /* Handle attribute((warn_unused_result)). Relies on gimple input. */
+ c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
+
+ /* Notice when OpenMP structured block constraints are violated. */
+ if (flag_openmp)
+ diagnose_omp_structured_block_errors (fndecl);
+
+ /* Finalize all nested functions now. */
+ cgn = cgraph_node (fndecl);
+ for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
+ c_gimple_diagnostics_recursively (cgn->decl);
+}
+
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
for the function definition.
@@ -6056,33 +6680,20 @@ finish_function (void)
{
tree fndecl = current_function_decl;
- /* When a function declaration is totally empty, e.g.
- void foo(void) { }
- (the argument list is irrelevant) the compstmt rule will not
- bother calling pushlevel/poplevel, which means we get here with
- the scope stack out of sync. Detect this situation by noticing
- that current_scope is still as store_parm_decls left it, and do
- a dummy push/pop to get back to consistency.
- Note that the call to pushlevel does not actually push another
- scope - see there for details. */
-
- if (current_scope->parm_flag && next_is_function_body)
- {
- pushlevel (0);
- poplevel (0, 0, 0);
- }
+ label_context_stack_se = label_context_stack_se->next;
+ label_context_stack_vm = label_context_stack_vm->next;
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
{
tree args = DECL_ARGUMENTS (fndecl);
for (; args; args = TREE_CHAIN (args))
- {
- tree type = TREE_TYPE (args);
- if (INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (args) = integer_type_node;
- }
+ {
+ tree type = TREE_TYPE (args);
+ if (INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ DECL_ARG_TYPE (args) = integer_type_node;
+ }
}
if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
@@ -6101,30 +6712,41 @@ finish_function (void)
/* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
If warn_main is -1 (-Wno-main) we don't want to be warned. */
if (!warn_main)
- pedwarn ("%Jreturn type of '%D' is not `int'", fndecl, fndecl);
+ pedwarn ("return type of %q+D is not %<int%>", fndecl);
}
else
{
-#ifdef DEFAULT_MAIN_RETURN
- /* Make it so that `main' always returns success by default. */
- DEFAULT_MAIN_RETURN;
-#else
if (flag_isoc99)
- c_expand_return (integer_zero_node);
+ {
+ tree stmt = c_finish_return (integer_zero_node);
+#ifdef USE_MAPPED_LOCATION
+ /* Hack. We don't want the middle-end to warn that this return
+ is unreachable, so we mark its location as special. Using
+ UNKNOWN_LOCATION has the problem that it gets clobbered in
+ annotate_one_with_locus. A cleaner solution might be to
+ ensure ! should_carry_locus_p (stmt), but that needs a flag.
+ */
+ SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION);
+#else
+ /* Hack. We don't want the middle-end to warn that this
+ return is unreachable, so put the statement on the
+ special line 0. */
+ annotate_with_file_line (stmt, input_filename, 0);
#endif
+ }
}
}
- finish_fname_decls ();
-
/* Tie off the statement tree for this function. */
- finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
+
+ finish_fname_decls ();
/* Complain if there's just no return statement. */
if (warn_return_type
&& TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
&& !current_function_returns_value && !current_function_returns_null
- /* Don't complain if we abort. */
+ /* Don't complain if we are no-return. */
&& !current_function_returns_abnormally
/* Don't warn for main(). */
&& !MAIN_NAME_P (DECL_NAME (fndecl))
@@ -6133,111 +6755,116 @@ finish_function (void)
/* Normally, with -Wreturn-type, flow will complain. Unless we're an
inline function, as we might never be compiled separately. */
&& DECL_INLINE (fndecl))
- warning ("no return statement in function returning non-void");
+ {
+ warning (OPT_Wreturn_type,
+ "no return statement in function returning non-void");
+ TREE_NO_WARNING (fndecl) = 1;
+ }
/* With just -Wextra, complain only if function returns both with
and without a value. */
if (extra_warnings
&& current_function_returns_value
&& current_function_returns_null)
- warning ("this function may return with or without a value");
+ warning (OPT_Wextra, "this function may return with or without a value");
- /* We're leaving the context of this function, so zap cfun. It's still in
- DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation. */
- cfun = NULL;
+ /* Store the end of the function, so that we get good line number
+ info for the epilogue. */
+ cfun->function_end_locus = input_location;
- /* ??? Objc emits functions after finalizing the compilation unit.
- This should be cleaned up later and this conditional removed. */
- if (!cgraph_global_info_ready)
- cgraph_finalize_function (fndecl, false);
- else
- c_expand_body (fndecl);
- current_function_decl = NULL;
-}
+ /* If we don't have ctors/dtors sections, and this is a static
+ constructor or destructor, it must be recorded now. */
+ if (DECL_STATIC_CONSTRUCTOR (fndecl)
+ && !targetm.have_ctors_dtors)
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+ if (DECL_STATIC_DESTRUCTOR (fndecl)
+ && !targetm.have_ctors_dtors)
+ static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
-/* Generate the RTL for a deferred function FNDECL. */
+ /* Finalize the ELF visibility for the function. */
+ c_determine_visibility (fndecl);
-void
-c_expand_deferred_function (tree fndecl)
-{
- /* DECL_INLINE or DECL_RESULT might got cleared after the inline
- function was deferred, e.g. in duplicate_decls. */
- if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
+ /* Genericize before inlining. Delay genericizing nested functions
+ until their parent function is genericized. Since finalizing
+ requires GENERIC, delay that as well. */
+
+ if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node
+ && !undef_nested_function)
{
- if (flag_inline_trees)
+ if (!decl_function_context (fndecl))
{
- timevar_push (TV_INTEGRATION);
- optimize_inline_calls (fndecl);
- timevar_pop (TV_INTEGRATION);
- }
- c_expand_body (fndecl);
- current_function_decl = NULL;
- }
-}
+ c_genericize (fndecl);
+ c_gimple_diagnostics_recursively (fndecl);
-/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero,
- then we are already in the process of generating RTL for another
- function. */
+ /* ??? Objc emits functions after finalizing the compilation unit.
+ This should be cleaned up later and this conditional removed. */
+ if (cgraph_global_info_ready)
+ {
+ c_expand_body (fndecl);
+ return;
+ }
-static void
-c_expand_body_1 (tree fndecl, int nested_p)
-{
- if (nested_p)
- /* Squirrel away our current state. */
- push_function_context ();
-
- /* Make sure that we will evaluate variable-sized types involved
- in our function's type. */
- put_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
- tree_rest_of_compilation (fndecl, nested_p);
-
- if (nested_p)
- /* Return to the enclosing function. */
- pop_function_context ();
-
- if (DECL_STATIC_CONSTRUCTOR (fndecl))
- {
- if (targetm.have_ctors_dtors)
- (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
+ cgraph_finalize_function (fndecl, false);
+ }
else
- static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+ {
+ /* Register this function with cgraph just far enough to get it
+ added to our parent's nested function list. Handy, since the
+ C front end doesn't have such a list. */
+ (void) cgraph_node (fndecl);
+ }
}
- if (DECL_STATIC_DESTRUCTOR (fndecl))
- {
- if (targetm.have_ctors_dtors)
- (* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
- else
- static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
- }
+ if (!decl_function_context (fndecl))
+ undef_nested_function = false;
+
+ /* We're leaving the context of this function, so zap cfun.
+ It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
+ tree_rest_of_compilation. */
+ cfun = NULL;
+ current_function_decl = NULL;
}
-/* Like c_expand_body_1 but only for unnested functions. */
+/* Generate the RTL for the body of FNDECL. */
void
c_expand_body (tree fndecl)
{
- if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
- c_expand_body_1 (fndecl, 0);
+ if (!DECL_INITIAL (fndecl)
+ || DECL_INITIAL (fndecl) == error_mark_node)
+ return;
+
+ tree_rest_of_compilation (fndecl);
+
+ if (DECL_STATIC_CONSTRUCTOR (fndecl)
+ && targetm.have_ctors_dtors)
+ targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
+ if (DECL_STATIC_DESTRUCTOR (fndecl)
+ && targetm.have_ctors_dtors)
+ targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
}
/* Check the declarations given in a for-loop for satisfying the C99
- constraints. */
-void
+ constraints. If exactly one such decl is found, return it. */
+
+tree
check_for_loop_decls (void)
{
- tree t;
+ struct c_binding *b;
+ tree one_decl = NULL_TREE;
+ int n_decls = 0;
+
if (!flag_isoc99)
{
/* If we get here, declarations have been used in a for loop without
the C99 for loop scope. This doesn't make much sense, so don't
allow it. */
- error ("'for' loop initial declaration used outside C99 mode");
- return;
+ error ("%<for%> loop initial declaration used outside C99 mode");
+ return NULL_TREE;
}
/* C99 subclause 6.8.5 paragraph 3:
@@ -6253,36 +6880,47 @@ check_for_loop_decls (void)
interpretation, to avoid creating an extension which later causes
problems. */
- for (t = current_scope->tags; t; t = TREE_CHAIN (t))
+ for (b = current_scope->bindings; b; b = b->prev)
{
- if (TREE_PURPOSE (t) != 0)
- {
- enum tree_code code = TREE_CODE (TREE_VALUE (t));
+ tree id = b->id;
+ tree decl = b->decl;
- if (code == RECORD_TYPE)
- error ("'struct %s' declared in 'for' loop initial declaration",
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- else if (code == UNION_TYPE)
- error ("'union %s' declared in 'for' loop initial declaration",
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- else
- error ("'enum %s' declared in 'for' loop initial declaration",
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
- }
+ if (!id)
+ continue;
- for (t = getdecls (); t; t = TREE_CHAIN (t))
- {
- if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
- error ("%Jdeclaration of non-variable '%D' in 'for' loop "
- "initial declaration", t, t);
- else if (TREE_STATIC (t))
- error ("%Jdeclaration of static variable '%D' in 'for' loop "
- "initial declaration", t, t);
- else if (DECL_EXTERNAL (t))
- error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
- "initial declaration", t, t);
+ switch (TREE_CODE (decl))
+ {
+ case VAR_DECL:
+ if (TREE_STATIC (decl))
+ error ("declaration of static variable %q+D in %<for%> loop "
+ "initial declaration", decl);
+ else if (DECL_EXTERNAL (decl))
+ error ("declaration of %<extern%> variable %q+D in %<for%> loop "
+ "initial declaration", decl);
+ break;
+
+ case RECORD_TYPE:
+ error ("%<struct %E%> declared in %<for%> loop initial declaration",
+ id);
+ break;
+ case UNION_TYPE:
+ error ("%<union %E%> declared in %<for%> loop initial declaration",
+ id);
+ break;
+ case ENUMERAL_TYPE:
+ error ("%<enum %E%> declared in %<for%> loop initial declaration",
+ id);
+ break;
+ default:
+ error ("declaration of non-variable %q+D in %<for%> loop "
+ "initial declaration", decl);
+ }
+
+ n_decls++;
+ one_decl = decl;
}
+
+ return n_decls == 1 ? one_decl : NULL_TREE;
}
/* Save and reinitialize the variables
@@ -6292,13 +6930,14 @@ void
c_push_function_context (struct function *f)
{
struct language_function *p;
- p = ggc_alloc (sizeof (struct language_function));
+ p = GGC_NEW (struct language_function);
f->language = p;
p->base.x_stmt_tree = c_stmt_tree;
- p->base.x_scope_stmt_stack = c_scope_stmt_stack;
- p->x_in_iteration_stmt = c_in_iteration_stmt;
- p->x_in_case_stmt = c_in_case_stmt;
+ p->x_break_label = c_break_label;
+ p->x_cont_label = c_cont_label;
+ p->x_switch_stack = c_switch_stack;
+ p->arg_info = current_function_arg_info;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->returns_abnormally = current_function_returns_abnormally;
@@ -6313,7 +6952,7 @@ c_pop_function_context (struct function *f)
{
struct language_function *p = f->language;
- if (DECL_SAVED_INSNS (current_function_decl) == 0
+ if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
&& DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
{
/* Stop pointing to the local nodes about to be freed. */
@@ -6324,9 +6963,10 @@ c_pop_function_context (struct function *f)
}
c_stmt_tree = p->base.x_stmt_tree;
- c_scope_stmt_stack = p->base.x_scope_stmt_stack;
- c_in_iteration_stmt = p->x_in_iteration_stmt;
- c_in_case_stmt = p->x_in_case_stmt;
+ c_break_label = p->x_break_label;
+ c_cont_label = p->x_cont_label;
+ c_switch_stack = p->x_switch_stack;
+ current_function_arg_info = p->arg_info;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;
@@ -6346,7 +6986,7 @@ c_dup_lang_specific_decl (tree decl)
if (!DECL_LANG_SPECIFIC (decl))
return;
- ld = ggc_alloc (sizeof (struct lang_decl));
+ ld = GGC_NEW (struct lang_decl);
memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl));
DECL_LANG_SPECIFIC (decl) = ld;
}
@@ -6356,16 +6996,6 @@ c_dup_lang_specific_decl (tree decl)
functions are not called from anywhere in the C front end, but as
these changes continue, that will change. */
-/* Returns nonzero if the current statement is a full expression,
- i.e. temporaries created during that statement should be destroyed
- at the end of the statement. */
-
-int
-stmts_are_full_exprs_p (void)
-{
- return 0;
-}
-
/* Returns the stmt_tree (if any) to which statements are currently
being added. If there is no active statement-tree, NULL is
returned. */
@@ -6376,74 +7006,26 @@ current_stmt_tree (void)
return &c_stmt_tree;
}
-/* Returns the stack of SCOPE_STMTs for the current function. */
-
-tree *
-current_scope_stmt_stack (void)
-{
- return &c_scope_stmt_stack;
-}
-
/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
C. */
int
-anon_aggr_type_p (tree node ATTRIBUTE_UNUSED)
+anon_aggr_type_p (tree ARG_UNUSED (node))
{
return 0;
}
-/* Dummy function in place of callback used by C++. */
-
-void
-extract_interface_info (void)
-{
-}
-
-/* Return a new COMPOUND_STMT, after adding it to the current
- statement tree. */
-
-tree
-c_begin_compound_stmt (void)
-{
- tree stmt;
-
- /* Create the COMPOUND_STMT. */
- stmt = add_stmt (build_stmt (COMPOUND_STMT, error_mark_node));
-
- return stmt;
-}
-
-/* Expand T (a DECL_STMT) if it declares an entity not handled by the
- common code. */
-
-void
-c_expand_decl_stmt (tree t)
-{
- tree decl = DECL_STMT_DECL (t);
-
- /* Expand nested functions. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_CONTEXT (decl) == current_function_decl
- && DECL_SAVED_TREE (decl))
- c_expand_body_1 (decl, 1);
-}
-
/* Return the global value of T as a symbol. */
tree
identifier_global_value (tree t)
{
- tree decl = IDENTIFIER_SYMBOL_VALUE (t);
- if (decl == 0 || DECL_FILE_SCOPE_P (decl))
- return decl;
+ struct c_binding *b;
- /* Shadowed by something else; find the true global value. */
- for (decl = global_scope->names; decl; decl = TREE_CHAIN (decl))
- if (DECL_NAME (decl) == t)
- return decl;
+ for (b = I_SYMBOL_BINDING (t); b; b = b->shadowed)
+ if (B_IN_FILE_SCOPE (b) || B_IN_EXTERNAL_SCOPE (b))
+ return b->decl;
- /* Only local values for this decl. */
return 0;
}
@@ -6453,12 +7035,15 @@ identifier_global_value (tree t)
void
record_builtin_type (enum rid rid_index, const char *name, tree type)
{
- tree id;
+ tree id, decl;
if (name == 0)
id = ridpointers[(int) rid_index];
else
id = get_identifier (name);
- pushdecl (build_decl (TYPE_DECL, id, type));
+ decl = build_decl (TYPE_DECL, id, type);
+ pushdecl (decl);
+ if (debug_hooks->type_decl)
+ debug_hooks->type_decl (decl, false);
}
/* Build the void_list_node (void_type_node having been created). */
@@ -6469,214 +7054,916 @@ build_void_list_node (void)
return t;
}
-/* Return something to represent absolute declarators containing a *.
- TARGET is the absolute declarator that the * contains.
- TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
- to apply to the pointer type, represented as identifiers, possible mixed
- with attributes.
+/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR. */
+
+struct c_parm *
+build_c_parm (struct c_declspecs *specs, tree attrs,
+ struct c_declarator *declarator)
+{
+ struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
+ ret->specs = specs;
+ ret->attrs = attrs;
+ ret->declarator = declarator;
+ return ret;
+}
- We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
- if attributes are present) and whose type is the modifier list. */
+/* Return a declarator with nested attributes. TARGET is the inner
+ declarator to which these attributes apply. ATTRS are the
+ attributes. */
-tree
-make_pointer_declarator (tree type_quals_attrs, tree target)
+struct c_declarator *
+build_attrs_declarator (tree attrs, struct c_declarator *target)
{
- tree quals, attrs;
- tree itarget = target;
- split_specs_attrs (type_quals_attrs, &quals, &attrs);
- if (attrs != NULL_TREE)
- itarget = tree_cons (attrs, target, NULL_TREE);
- return build1 (INDIRECT_REF, quals, itarget);
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_attrs;
+ ret->declarator = target;
+ ret->u.attrs = attrs;
+ return ret;
}
-/* A wrapper around lhd_set_decl_assembler_name that gives static
- variables their C names if they are at file scope and only one
- translation unit is being compiled, for backwards compatibility
- with certain bizarre assembler hacks (like crtstuff.c). */
+/* Return a declarator for a function with arguments specified by ARGS
+ and return type specified by TARGET. */
-void
-c_static_assembler_name (tree decl)
+struct c_declarator *
+build_function_declarator (struct c_arg_info *args,
+ struct c_declarator *target)
{
- if (num_in_fnames == 1
- && !TREE_PUBLIC (decl) && DECL_CONTEXT (decl)
- && TREE_CODE (DECL_CONTEXT (decl)) == TRANSLATION_UNIT_DECL)
- SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
- else
- lhd_set_decl_assembler_name (decl);
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_function;
+ ret->declarator = target;
+ ret->u.arg_info = args;
+ return ret;
}
-/* Hash and equality functions for link_hash_table: key off
- DECL_ASSEMBLER_NAME. */
+/* Return a declarator for the identifier IDENT (which may be
+ NULL_TREE for an abstract declarator). */
-static hashval_t
-link_hash_hash (const void *x_p)
+struct c_declarator *
+build_id_declarator (tree ident)
{
- tree x = (tree)x_p;
- return (hashval_t) (long)DECL_ASSEMBLER_NAME (x);
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_id;
+ ret->declarator = 0;
+ ret->u.id = ident;
+ /* Default value - may get reset to a more precise location. */
+ ret->id_loc = input_location;
+ return ret;
}
-static int
-link_hash_eq (const void *x1_p, const void *x2_p)
+/* Return something to represent absolute declarators containing a *.
+ TARGET is the absolute declarator that the * contains.
+ TYPE_QUALS_ATTRS is a structure for type qualifiers and attributes
+ to apply to the pointer type. */
+
+struct c_declarator *
+make_pointer_declarator (struct c_declspecs *type_quals_attrs,
+ struct c_declarator *target)
{
- tree x1 = (tree)x1_p;
- tree x2 = (tree)x2_p;
- return DECL_ASSEMBLER_NAME (x1) == DECL_ASSEMBLER_NAME (x2);
+ tree attrs;
+ int quals = 0;
+ struct c_declarator *itarget = target;
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ if (type_quals_attrs)
+ {
+ attrs = type_quals_attrs->attrs;
+ quals = quals_from_declspecs (type_quals_attrs);
+ if (attrs != NULL_TREE)
+ itarget = build_attrs_declarator (attrs, target);
+ }
+ ret->kind = cdk_pointer;
+ ret->declarator = itarget;
+ ret->u.pointer_quals = quals;
+ return ret;
}
-/* Propagate information between definitions and uses between multiple
- translation units in TU_LIST based on linkage rules. */
+/* Return a pointer to a structure for an empty list of declaration
+ specifiers. */
-void
-merge_translation_unit_decls (void)
+struct c_declspecs *
+build_null_declspecs (void)
{
- const tree tu_list = current_file_decl;
- tree tu;
- tree decl;
- htab_t link_hash_table;
- tree block;
+ struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
+ ret->type = 0;
+ ret->decl_attr = 0;
+ ret->attrs = 0;
+ ret->typespec_word = cts_none;
+ ret->storage_class = csc_none;
+ ret->declspecs_seen_p = false;
+ ret->type_seen_p = false;
+ ret->non_sc_seen_p = false;
+ ret->typedef_p = false;
+ ret->tag_defined_p = false;
+ ret->explicit_signed_p = false;
+ ret->deprecated_p = false;
+ ret->default_int_p = false;
+ ret->long_p = false;
+ ret->long_long_p = false;
+ ret->short_p = false;
+ ret->signed_p = false;
+ ret->unsigned_p = false;
+ ret->complex_p = false;
+ ret->inline_p = false;
+ ret->thread_p = false;
+ ret->const_p = false;
+ ret->volatile_p = false;
+ ret->restrict_p = false;
+ return ret;
+}
- /* Create the BLOCK that poplevel would have created, but don't
- actually call poplevel since that's expensive. */
- block = make_node (BLOCK);
- BLOCK_VARS (block) = current_scope->names;
- TREE_USED (block) = 1;
- DECL_INITIAL (current_file_decl) = block;
+/* Add the type qualifier QUAL to the declaration specifiers SPECS,
+ returning SPECS. */
- /* If only one translation unit seen, no copying necessary. */
- if (TREE_CHAIN (tu_list) == NULL_TREE)
- return;
+struct c_declspecs *
+declspecs_add_qual (struct c_declspecs *specs, tree qual)
+{
+ enum rid i;
+ bool dupe = false;
+ specs->non_sc_seen_p = true;
+ specs->declspecs_seen_p = true;
+ gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
+ && C_IS_RESERVED_WORD (qual));
+ i = C_RID_CODE (qual);
+ switch (i)
+ {
+ case RID_CONST:
+ dupe = specs->const_p;
+ specs->const_p = true;
+ break;
+ case RID_VOLATILE:
+ dupe = specs->volatile_p;
+ specs->volatile_p = true;
+ break;
+ case RID_RESTRICT:
+ dupe = specs->restrict_p;
+ specs->restrict_p = true;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (dupe && pedantic && !flag_isoc99)
+ pedwarn ("duplicate %qE", qual);
+ return specs;
+}
- link_hash_table = htab_create (1021, link_hash_hash, link_hash_eq, NULL);
+/* Add the type specifier TYPE to the declaration specifiers SPECS,
+ returning SPECS. */
- /* Enter any actual definitions into the hash table. */
- for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
- for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
- if (TREE_PUBLIC (decl) && ! DECL_EXTERNAL (decl))
+struct c_declspecs *
+declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
+{
+ tree type = spec.spec;
+ specs->non_sc_seen_p = true;
+ specs->declspecs_seen_p = true;
+ specs->type_seen_p = true;
+ if (TREE_DEPRECATED (type))
+ specs->deprecated_p = true;
+
+ /* Handle type specifier keywords. */
+ if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type))
+ {
+ enum rid i = C_RID_CODE (type);
+ if (specs->type)
+ {
+ error ("two or more data types in declaration specifiers");
+ return specs;
+ }
+ if ((int) i <= (int) RID_LAST_MODIFIER)
{
- PTR *slot;
- slot = htab_find_slot (link_hash_table, decl, INSERT);
-
- /* If we've already got a definition, work out which one is
- the real one, put it into the hash table, and make the
- other one DECL_EXTERNAL. This is important to avoid
- putting out two definitions of the same symbol in the
- assembly output. */
- if (*slot != NULL)
+ /* "long", "short", "signed", "unsigned" or "_Complex". */
+ bool dupe = false;
+ switch (i)
{
- tree old_decl = (tree) *slot;
-
- /* If this is weak or common or whatever, suppress it
- in favor of the other definition. */
- if (DECL_WEAK (decl))
- DECL_EXTERNAL (decl) = 1;
- else if (DECL_WEAK (old_decl) && ! DECL_WEAK (decl))
- DECL_EXTERNAL (old_decl) = 1;
- else if (DECL_COMMON (decl) || DECL_ONE_ONLY (decl))
- DECL_EXTERNAL (decl) = 1;
- else if (DECL_COMMON (old_decl) || DECL_ONE_ONLY (old_decl))
- DECL_EXTERNAL (old_decl) = 1;
-
- if (DECL_EXTERNAL (decl))
+ case RID_LONG:
+ if (specs->long_long_p)
{
- DECL_INITIAL (decl) = NULL_TREE;
- DECL_COMMON (decl) = 0;
- DECL_ONE_ONLY (decl) = 0;
- DECL_WEAK (decl) = 0;
+ error ("%<long long long%> is too long for GCC");
+ break;
}
- else if (DECL_EXTERNAL (old_decl))
+ if (specs->long_p)
{
- DECL_INITIAL (old_decl) = NULL_TREE;
- DECL_COMMON (old_decl) = 0;
- DECL_ONE_ONLY (old_decl) = 0;
- DECL_WEAK (old_decl) = 0;
- *slot = decl;
+ if (specs->typespec_word == cts_double)
+ {
+ error ("both %<long long%> and %<double%> in "
+ "declaration specifiers");
+ break;
+ }
+ if (pedantic && !flag_isoc99 && !in_system_header
+ && warn_long_long)
+ pedwarn ("ISO C90 does not support %<long long%>");
+ specs->long_long_p = 1;
+ break;
}
+ if (specs->short_p)
+ error ("both %<long%> and %<short%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<long%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<long%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<long%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat32)
+ error ("both %<long%> and %<_Decimal32%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat64)
+ error ("both %<long%> and %<_Decimal64%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat128)
+ error ("both %<long%> and %<_Decimal128%> in "
+ "declaration specifiers");
else
- {
- error ("%Jredefinition of global '%D'", decl, decl);
- error ("%J'%D' previously defined here", old_decl, old_decl);
- }
+ specs->long_p = true;
+ break;
+ case RID_SHORT:
+ dupe = specs->short_p;
+ if (specs->long_p)
+ error ("both %<long%> and %<short%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<short%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<short%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<short%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<short%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat32)
+ error ("both %<short%> and %<_Decimal32%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat64)
+ error ("both %<short%> and %<_Decimal64%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat128)
+ error ("both %<short%> and %<_Decimal128%> in "
+ "declaration specifiers");
+ else
+ specs->short_p = true;
+ break;
+ case RID_SIGNED:
+ dupe = specs->signed_p;
+ if (specs->unsigned_p)
+ error ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<signed%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<signed%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<signed%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat32)
+ error ("both %<signed%> and %<_Decimal32%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat64)
+ error ("both %<signed%> and %<_Decimal64%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat128)
+ error ("both %<signed%> and %<_Decimal128%> in "
+ "declaration specifiers");
+ else
+ specs->signed_p = true;
+ break;
+ case RID_UNSIGNED:
+ dupe = specs->unsigned_p;
+ if (specs->signed_p)
+ error ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<unsigned%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat32)
+ error ("both %<unsigned%> and %<_Decimal32%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat64)
+ error ("both %<unsigned%> and %<_Decimal64%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat128)
+ error ("both %<unsigned%> and %<_Decimal128%> in "
+ "declaration specifiers");
+ else
+ specs->unsigned_p = true;
+ break;
+ case RID_COMPLEX:
+ dupe = specs->complex_p;
+ if (pedantic && !flag_isoc99 && !in_system_header)
+ pedwarn ("ISO C90 does not support complex types");
+ if (specs->typespec_word == cts_void)
+ error ("both %<complex%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat32)
+ error ("both %<complex%> and %<_Decimal32%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat64)
+ error ("both %<complex%> and %<_Decimal64%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat128)
+ error ("both %<complex%> and %<_Decimal128%> in "
+ "declaration specifiers");
+ else
+ specs->complex_p = true;
+ break;
+ default:
+ gcc_unreachable ();
}
- else
- *slot = decl;
+
+ if (dupe)
+ error ("duplicate %qE", type);
+
+ return specs;
}
+ else
+ {
+ /* "void", "_Bool", "char", "int", "float" or "double". */
+ if (specs->typespec_word != cts_none)
+ {
+ error ("two or more data types in declaration specifiers");
+ return specs;
+ }
+ switch (i)
+ {
+ case RID_VOID:
+ if (specs->long_p)
+ error ("both %<long%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<complex%> and %<void%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_void;
+ return specs;
+ case RID_BOOL:
+ if (specs->long_p)
+ error ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_bool;
+ return specs;
+ case RID_CHAR:
+ if (specs->long_p)
+ error ("both %<long%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<char%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_char;
+ return specs;
+ case RID_INT:
+ specs->typespec_word = cts_int;
+ return specs;
+ case RID_FLOAT:
+ if (specs->long_p)
+ error ("both %<long%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_float;
+ return specs;
+ case RID_DOUBLE:
+ if (specs->long_long_p)
+ error ("both %<long long%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<double%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_double;
+ return specs;
+ case RID_DFLOAT32:
+ case RID_DFLOAT64:
+ case RID_DFLOAT128:
+ {
+ const char *str;
+ if (i == RID_DFLOAT32)
+ str = "_Decimal32";
+ else if (i == RID_DFLOAT64)
+ str = "_Decimal64";
+ else
+ str = "_Decimal128";
+ if (specs->long_long_p)
+ error ("both %<long long%> and %<%s%> in "
+ "declaration specifiers", str);
+ if (specs->long_p)
+ error ("both %<long%> and %<%s%> in "
+ "declaration specifiers", str);
+ else if (specs->short_p)
+ error ("both %<short%> and %<%s%> in "
+ "declaration specifiers", str);
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<%s%> in "
+ "declaration specifiers", str);
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<%s%> in "
+ "declaration specifiers", str);
+ else if (specs->complex_p)
+ error ("both %<complex%> and %<%s%> in "
+ "declaration specifiers", str);
+ else if (i == RID_DFLOAT32)
+ specs->typespec_word = cts_dfloat32;
+ else if (i == RID_DFLOAT64)
+ specs->typespec_word = cts_dfloat64;
+ else
+ specs->typespec_word = cts_dfloat128;
+ }
+ if (!targetm.decimal_float_supported_p ())
+ error ("decimal floating point not supported for this target");
+ if (pedantic)
+ pedwarn ("ISO C does not support decimal floating point");
+ return specs;
+ default:
+ /* ObjC reserved word "id", handled below. */
+ break;
+ }
+ }
+ }
- /* Now insert the desired information from all the definitions
- into any plain declarations. */
- for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
- for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
- if (TREE_PUBLIC (decl) && DECL_EXTERNAL (decl))
+ /* Now we have a typedef (a TYPE_DECL node), an identifier (some
+ form of ObjC type, cases such as "int" and "long" being handled
+ above), a TYPE (struct, union, enum and typeof specifiers) or an
+ ERROR_MARK. In none of these cases may there have previously
+ been any type specifiers. */
+ if (specs->type || specs->typespec_word != cts_none
+ || specs->long_p || specs->short_p || specs->signed_p
+ || specs->unsigned_p || specs->complex_p)
+ error ("two or more data types in declaration specifiers");
+ else if (TREE_CODE (type) == TYPE_DECL)
+ {
+ if (TREE_TYPE (type) == error_mark_node)
+ ; /* Allow the type to default to int to avoid cascading errors. */
+ else
{
- tree global_decl;
- global_decl = htab_find (link_hash_table, decl);
+ specs->type = TREE_TYPE (type);
+ specs->decl_attr = DECL_ATTRIBUTES (type);
+ specs->typedef_p = true;
+ specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+ }
+ }
+ else if (TREE_CODE (type) == IDENTIFIER_NODE)
+ {
+ tree t = lookup_name (type);
+ if (!t || TREE_CODE (t) != TYPE_DECL)
+ error ("%qE fails to be a typedef or built in type", type);
+ else if (TREE_TYPE (t) == error_mark_node)
+ ;
+ else
+ specs->type = TREE_TYPE (t);
+ }
+ else if (TREE_CODE (type) != ERROR_MARK)
+ {
+ if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
+ specs->tag_defined_p = true;
+ if (spec.kind == ctsk_typeof)
+ specs->typedef_p = true;
+ specs->type = type;
+ }
- if (! global_decl)
- continue;
+ return specs;
+}
- /* Print any appropriate error messages, and partially merge
- the decls. */
- (void) duplicate_decls (decl, global_decl);
+/* Add the storage class specifier or function specifier SCSPEC to the
+ declaration specifiers SPECS, returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
+{
+ enum rid i;
+ enum c_storage_class n = csc_none;
+ bool dupe = false;
+ specs->declspecs_seen_p = true;
+ gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE
+ && C_IS_RESERVED_WORD (scspec));
+ i = C_RID_CODE (scspec);
+ if (extra_warnings && specs->non_sc_seen_p)
+ warning (OPT_Wextra, "%qE is not at beginning of declaration", scspec);
+ switch (i)
+ {
+ case RID_INLINE:
+ /* C99 permits duplicate inline. Although of doubtful utility,
+ it seems simplest to permit it in gnu89 mode as well, as
+ there is also little utility in maintaining this as a
+ difference between gnu89 and C99 inline. */
+ dupe = false;
+ specs->inline_p = true;
+ break;
+ case RID_THREAD:
+ dupe = specs->thread_p;
+ if (specs->storage_class == csc_auto)
+ error ("%<__thread%> used with %<auto%>");
+ else if (specs->storage_class == csc_register)
+ error ("%<__thread%> used with %<register%>");
+ else if (specs->storage_class == csc_typedef)
+ error ("%<__thread%> used with %<typedef%>");
+ else
+ specs->thread_p = true;
+ break;
+ case RID_AUTO:
+ n = csc_auto;
+ break;
+ case RID_EXTERN:
+ n = csc_extern;
+ /* Diagnose "__thread extern". */
+ if (specs->thread_p)
+ error ("%<__thread%> before %<extern%>");
+ break;
+ case RID_REGISTER:
+ n = csc_register;
+ break;
+ case RID_STATIC:
+ n = csc_static;
+ /* Diagnose "__thread static". */
+ if (specs->thread_p)
+ error ("%<__thread%> before %<static%>");
+ break;
+ case RID_TYPEDEF:
+ n = csc_typedef;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (n != csc_none && n == specs->storage_class)
+ dupe = true;
+ if (dupe)
+ error ("duplicate %qE", scspec);
+ if (n != csc_none)
+ {
+ if (specs->storage_class != csc_none && n != specs->storage_class)
+ {
+ error ("multiple storage classes in declaration specifiers");
}
+ else
+ {
+ specs->storage_class = n;
+ if (n != csc_extern && n != csc_static && specs->thread_p)
+ {
+ error ("%<__thread%> used with %qE", scspec);
+ specs->thread_p = false;
+ }
+ }
+ }
+ return specs;
+}
+
+/* Add the attributes ATTRS to the declaration specifiers SPECS,
+ returning SPECS. */
- htab_delete (link_hash_table);
+struct c_declspecs *
+declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
+{
+ specs->attrs = chainon (attrs, specs->attrs);
+ specs->declspecs_seen_p = true;
+ return specs;
}
-/* Perform final processing on file-scope data. */
+/* Combine "long", "short", "signed", "unsigned" and "_Complex" type
+ specifiers with any other type specifier to determine the resulting
+ type. This is where ISO C checks on complex types are made, since
+ "_Complex long" is a prefix of the valid ISO C type "_Complex long
+ double". */
-void
-c_write_global_declarations(void)
+struct c_declspecs *
+finish_declspecs (struct c_declspecs *specs)
{
- tree link;
+ /* If a type was specified as a whole, we have no modifiers and are
+ done. */
+ if (specs->type != NULL_TREE)
+ {
+ gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p
+ && !specs->complex_p);
+ return specs;
+ }
- for (link = current_file_decl; link; link = TREE_CHAIN (link))
+ /* If none of "void", "_Bool", "char", "int", "float" or "double"
+ has been specified, treat it as "int" unless "_Complex" is
+ present and there are no other specifiers. If we just have
+ "_Complex", it is equivalent to "_Complex double", but e.g.
+ "_Complex short" is equivalent to "_Complex short int". */
+ if (specs->typespec_word == cts_none)
{
- tree globals = BLOCK_VARS (DECL_INITIAL (link));
- int len = list_length (globals);
- tree *vec = xmalloc (sizeof (tree) * len);
- int i;
- tree decl;
+ if (specs->long_p || specs->short_p
+ || specs->signed_p || specs->unsigned_p)
+ {
+ specs->typespec_word = cts_int;
+ }
+ else if (specs->complex_p)
+ {
+ specs->typespec_word = cts_double;
+ if (pedantic)
+ pedwarn ("ISO C does not support plain %<complex%> meaning "
+ "%<double complex%>");
+ }
+ else
+ {
+ specs->typespec_word = cts_int;
+ specs->default_int_p = true;
+ /* We don't diagnose this here because grokdeclarator will
+ give more specific diagnostics according to whether it is
+ a function definition. */
+ }
+ }
+
+ /* If "signed" was specified, record this to distinguish "int" and
+ "signed int" in the case of a bit-field with
+ -funsigned-bitfields. */
+ specs->explicit_signed_p = specs->signed_p;
+
+ /* Now compute the actual type. */
+ switch (specs->typespec_word)
+ {
+ case cts_void:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p
+ && !specs->complex_p);
+ specs->type = void_type_node;
+ break;
+ case cts_bool:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p
+ && !specs->complex_p);
+ specs->type = boolean_type_node;
+ break;
+ case cts_char:
+ gcc_assert (!specs->long_p && !specs->short_p);
+ gcc_assert (!(specs->signed_p && specs->unsigned_p));
+ if (specs->signed_p)
+ specs->type = signed_char_type_node;
+ else if (specs->unsigned_p)
+ specs->type = unsigned_char_type_node;
+ else
+ specs->type = char_type_node;
+ if (specs->complex_p)
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support complex integer types");
+ specs->type = build_complex_type (specs->type);
+ }
+ break;
+ case cts_int:
+ gcc_assert (!(specs->long_p && specs->short_p));
+ gcc_assert (!(specs->signed_p && specs->unsigned_p));
+ if (specs->long_long_p)
+ specs->type = (specs->unsigned_p
+ ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+ else if (specs->long_p)
+ specs->type = (specs->unsigned_p
+ ? long_unsigned_type_node
+ : long_integer_type_node);
+ else if (specs->short_p)
+ specs->type = (specs->unsigned_p
+ ? short_unsigned_type_node
+ : short_integer_type_node);
+ else
+ specs->type = (specs->unsigned_p
+ ? unsigned_type_node
+ : integer_type_node);
+ if (specs->complex_p)
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support complex integer types");
+ specs->type = build_complex_type (specs->type);
+ }
+ break;
+ case cts_float:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p);
+ specs->type = (specs->complex_p
+ ? complex_float_type_node
+ : float_type_node);
+ break;
+ case cts_double:
+ gcc_assert (!specs->long_long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p);
+ if (specs->long_p)
+ {
+ specs->type = (specs->complex_p
+ ? complex_long_double_type_node
+ : long_double_type_node);
+ }
+ else
+ {
+ specs->type = (specs->complex_p
+ ? complex_double_type_node
+ : double_type_node);
+ }
+ break;
+ case cts_dfloat32:
+ case cts_dfloat64:
+ case cts_dfloat128:
+ gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p && !specs->complex_p);
+ if (specs->typespec_word == cts_dfloat32)
+ specs->type = dfloat32_type_node;
+ else if (specs->typespec_word == cts_dfloat64)
+ specs->type = dfloat64_type_node;
+ else
+ specs->type = dfloat128_type_node;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ return specs;
+}
- /* Process the decls in the order they were written. */
+/* Synthesize a function which calls all the global ctors or global
+ dtors in this file. This is only used for targets which do not
+ support .ctors/.dtors sections. FIXME: Migrate into cgraph. */
+static void
+build_cdtor (int method_type, tree cdtors)
+{
+ tree body = 0;
+
+ if (!cdtors)
+ return;
- for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
- vec[i] = decl;
+ for (; cdtors; cdtors = TREE_CHAIN (cdtors))
+ append_to_statement_list (build_function_call (TREE_VALUE (cdtors), 0),
+ &body);
- wrapup_global_declarations (vec, len);
+ cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
+}
- check_global_declarations (vec, len);
+/* A subroutine of c_write_global_declarations. Perform final processing
+ on one file scope's declarations (or the external scope's declarations),
+ GLOBALS. */
- /* Clean up. */
- free (vec);
+static void
+c_write_global_declarations_1 (tree globals)
+{
+ tree decl;
+ bool reconsider;
+
+ /* Process the decls in the order they were written. */
+ for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ {
+ /* Check for used but undefined static functions using the C
+ standard's definition of "used", and set TREE_NO_WARNING so
+ that check_global_declarations doesn't repeat the check. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INITIAL (decl) == 0
+ && DECL_EXTERNAL (decl)
+ && !TREE_PUBLIC (decl)
+ && C_DECL_USED (decl))
+ {
+ pedwarn ("%q+F used but never defined", decl);
+ TREE_NO_WARNING (decl) = 1;
+ }
+
+ wrapup_global_declaration_1 (decl);
}
+
+ do
+ {
+ reconsider = false;
+ for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ reconsider |= wrapup_global_declaration_2 (decl);
+ }
+ while (reconsider);
+
+ for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ check_global_declaration_1 (decl);
+}
+
+/* A subroutine of c_write_global_declarations Emit debug information for each
+ of the declarations in GLOBALS. */
+
+static void
+c_write_global_declarations_2 (tree globals)
+{
+ tree decl;
+
+ for (decl = globals; decl ; decl = TREE_CHAIN (decl))
+ debug_hooks->global_decl (decl);
}
-/* Reset the parser's state in preparation for a new file. */
+/* Preserve the external declarations scope across a garbage collect. */
+static GTY(()) tree ext_block;
void
-c_reset_state (void)
+c_write_global_declarations (void)
{
- tree link;
- tree file_scope_decl;
-
- /* Pop the global scope. */
- if (current_scope != global_scope)
- current_scope = global_scope;
- file_scope_decl = current_file_decl;
- DECL_INITIAL (file_scope_decl) = poplevel (1, 0, 0);
- BLOCK_SUPERCONTEXT (DECL_INITIAL (file_scope_decl)) = file_scope_decl;
- truly_local_externals = NULL_TREE;
-
- /* Start a new global binding level. */
- pushlevel (0);
- global_scope = current_scope;
- current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
- TREE_CHAIN (current_file_decl) = file_scope_decl;
-
- /* Reintroduce the builtin declarations. */
- for (link = first_builtin_decl;
- link != TREE_CHAIN (last_builtin_decl);
- link = TREE_CHAIN (link))
- pushdecl (copy_node (link));
+ tree t;
+
+ /* We don't want to do this if generating a PCH. */
+ if (pch_file)
+ return;
+
+ /* Don't waste time on further processing if -fsyntax-only or we've
+ encountered errors. */
+ if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in))
+ return;
+
+ /* Close the external scope. */
+ ext_block = pop_scope ();
+ external_scope = 0;
+ gcc_assert (!current_scope);
+
+ if (ext_block)
+ {
+ tree tmp = BLOCK_VARS (ext_block);
+ int flags;
+ FILE * stream = dump_begin (TDI_tu, &flags);
+ if (stream && tmp)
+ {
+ dump_node (tmp, flags & ~TDF_SLIM, stream);
+ dump_end (TDI_tu, stream);
+ }
+ }
+
+ /* Process all file scopes in this compilation, and the external_scope,
+ through wrapup_global_declarations and check_global_declarations. */
+ for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
+ c_write_global_declarations_1 (BLOCK_VARS (ext_block));
+
+ /* Generate functions to call static constructors and destructors
+ for targets that do not support .ctors/.dtors sections. These
+ functions have magic names which are detected by collect2. */
+ build_cdtor ('I', static_ctors); static_ctors = 0;
+ build_cdtor ('D', static_dtors); static_dtors = 0;
+
+ /* We're done parsing; proceed to optimize and emit assembly.
+ FIXME: shouldn't be the front end's responsibility to call this. */
+ cgraph_optimize ();
+
+ /* After cgraph has had a chance to emit everything that's going to
+ be emitted, output debug information for globals. */
+ if (errorcount == 0 && sorrycount == 0)
+ {
+ timevar_push (TV_SYMOUT);
+ for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
+ c_write_global_declarations_2 (BLOCK_VARS (ext_block));
+ timevar_pop (TV_SYMOUT);
+ }
+
+ ext_block = NULL;
}
#include "gt-c-decl.h"
diff --git a/contrib/gcc/c-lex.c b/contrib/gcc/c-lex.c
index aba571f..108bc5c 100644
--- a/contrib/gcc/c-lex.c
+++ b/contrib/gcc/c-lex.c
@@ -1,6 +1,7 @@
/* Mainly the interface between cpplib and the C front ends.
Copyright (C) 1987, 1988, 1989, 1992, 1994, 1995, 1996, 1997
- 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -27,7 +28,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "real.h"
#include "rtl.h"
#include "tree.h"
-#include "expr.h"
#include "input.h"
#include "output.h"
#include "c-tree.h"
@@ -42,28 +42,29 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "splay-tree.h"
#include "debug.h"
-/* The current line map. */
-static const struct line_map *map;
-
/* We may keep statistics about how long which files took to compile. */
static int header_time, body_time;
static splay_tree file_info_tree;
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE TYPE_PRECISION (wchar_type_node)
-
-/* Number of bytes in a wide character. */
-#define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
-
int pending_lang_change; /* If we need to switch languages - C++ only */
int c_header_level; /* depth in C headers - C++ only */
+/* If we need to translate characters received. This is tri-state:
+ 0 means use only the untranslated string; 1 means use only
+ the translated string; -1 means chain the translated string
+ to the untranslated one. */
+int c_lex_string_translate = 1;
+
+/* True if strings should be passed to the caller of c_lex completely
+ unmolested (no concatenation, no translation). */
+bool c_lex_return_raw_strings = false;
+
static tree interpret_integer (const cpp_token *, unsigned int);
static tree interpret_float (const cpp_token *, unsigned int);
-static enum integer_type_kind
- narrowest_unsigned_type (tree, unsigned int);
-static enum integer_type_kind
- narrowest_signed_type (tree, unsigned int);
+static enum integer_type_kind narrowest_unsigned_type
+ (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
+static enum integer_type_kind narrowest_signed_type
+ (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
static enum cpp_ttype lex_string (const cpp_token *, tree *, bool);
static tree lex_charconst (const cpp_token *);
static void update_header_times (const char *);
@@ -80,10 +81,8 @@ init_c_lex (void)
struct cpp_callbacks *cb;
struct c_fileinfo *toplevel;
- /* Set up filename timing. Must happen before cpp_read_main_file. */
- file_info_tree = splay_tree_new ((splay_tree_compare_fn)strcmp,
- 0,
- (splay_tree_delete_value_fn)free);
+ /* The get_fileinfo data structure must be initialized before
+ cpp_read_main_file is called. */
toplevel = get_fileinfo ("<top level>");
if (flag_detailed_statistics)
{
@@ -102,8 +101,8 @@ init_c_lex (void)
/* Set the debug callbacks if we can use them. */
if (debug_info_level == DINFO_LEVEL_VERBOSE
- && (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG
- || write_symbols == VMS_AND_DWARF2_DEBUG))
+ && (write_symbols == DWARF2_DEBUG
+ || write_symbols == VMS_AND_DWARF2_DEBUG))
{
cb->define = cb_define;
cb->undef = cb_undef;
@@ -116,11 +115,16 @@ get_fileinfo (const char *name)
splay_tree_node n;
struct c_fileinfo *fi;
+ if (!file_info_tree)
+ file_info_tree = splay_tree_new ((splay_tree_compare_fn) strcmp,
+ 0,
+ (splay_tree_delete_value_fn) free);
+
n = splay_tree_lookup (file_info_tree, (splay_tree_key) name);
if (n)
return (struct c_fileinfo *) n->value;
- fi = xmalloc (sizeof (struct c_fileinfo));
+ fi = XNEW (struct c_fileinfo);
fi->time = 0;
fi->interface_only = 0;
fi->interface_unknown = 1;
@@ -145,7 +149,7 @@ update_header_times (const char *name)
}
static int
-dump_one_header (splay_tree_node n, void *dummy ATTRIBUTE_UNUSED)
+dump_one_header (splay_tree_node n, void * ARG_UNUSED (dummy))
{
print_time ((const char *) n->key,
((struct c_fileinfo *) n->value)->time);
@@ -163,26 +167,26 @@ dump_time_statistics (void)
print_time ("header files (total)", header_time);
print_time ("main file (total)", this_time - body_time);
fprintf (stderr, "ratio = %g : 1\n",
- (double)header_time / (double)(this_time - body_time));
+ (double) header_time / (double) (this_time - body_time));
fprintf (stderr, "\n******\n");
splay_tree_foreach (file_info_tree, dump_one_header, 0);
}
static void
-cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED,
- unsigned int line ATTRIBUTE_UNUSED,
- const cpp_string *str ATTRIBUTE_UNUSED)
+cb_ident (cpp_reader * ARG_UNUSED (pfile),
+ unsigned int ARG_UNUSED (line),
+ const cpp_string * ARG_UNUSED (str))
{
#ifdef ASM_OUTPUT_IDENT
- if (! flag_no_ident)
+ if (!flag_no_ident)
{
/* Convert escapes in the string. */
cpp_string cstr = { 0, 0 };
if (cpp_interpret_string (pfile, str, 1, &cstr, false))
{
ASM_OUTPUT_IDENT (asm_out_file, (const char *) cstr.text);
- free ((void *)cstr.text);
+ free ((void *) cstr.text);
}
}
#endif
@@ -191,34 +195,44 @@ cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED,
/* Called at the start of every non-empty line. TOKEN is the first
lexed token on the line. Used for diagnostic line numbers. */
static void
-cb_line_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const cpp_token *token,
+cb_line_change (cpp_reader * ARG_UNUSED (pfile), const cpp_token *token,
int parsing_args)
{
- if (token->type == CPP_EOF || parsing_args)
- return;
-
- input_line = SOURCE_LINE (map, token->line);
+ if (token->type != CPP_EOF && !parsing_args)
+#ifdef USE_MAPPED_LOCATION
+ input_location = token->src_loc;
+#else
+ {
+ source_location loc = token->src_loc;
+ const struct line_map *map = linemap_lookup (&line_table, loc);
+ input_line = SOURCE_LINE (map, loc);
+ }
+#endif
}
void
fe_file_change (const struct line_map *new_map)
{
if (new_map == NULL)
- {
- map = NULL;
- return;
- }
+ return;
if (new_map->reason == LC_ENTER)
{
/* Don't stack the main buffer on the input stack;
we already did in compile_file. */
- if (map != NULL)
+ if (!MAIN_FILE_P (new_map))
{
- int included_at = SOURCE_LINE (new_map - 1, new_map->from_line - 1);
+#ifdef USE_MAPPED_LOCATION
+ int included_at = LAST_SOURCE_LINE_LOCATION (new_map - 1);
+
+ input_location = included_at;
+ push_srcloc (new_map->start_location);
+#else
+ int included_at = LAST_SOURCE_LINE (new_map - 1);
input_line = included_at;
push_srcloc (new_map->to_file, 1);
+#endif
(*debug_hooks->start_source_file) (included_at, new_map->to_file);
#ifndef NO_IMPLICIT_EXTERN_C
if (c_header_level)
@@ -237,7 +251,7 @@ fe_file_change (const struct line_map *new_map)
if (c_header_level && --c_header_level == 0)
{
if (new_map->sysp == 2)
- warning ("badly nested C headers from preprocessor");
+ warning (0, "badly nested C headers from preprocessor");
--pending_lang_change;
}
#endif
@@ -248,16 +262,16 @@ fe_file_change (const struct line_map *new_map)
update_header_times (new_map->to_file);
in_system_header = new_map->sysp != 0;
+#ifdef USE_MAPPED_LOCATION
+ input_location = new_map->start_location;
+#else
input_filename = new_map->to_file;
input_line = new_map->to_line;
- map = new_map;
-
- /* Hook for C++. */
- extract_interface_info ();
+#endif
}
static void
-cb_def_pragma (cpp_reader *pfile, unsigned int line)
+cb_def_pragma (cpp_reader *pfile, source_location loc)
{
/* Issue a warning message if we have been asked to do so. Ignore
unknown pragmas in system headers unless an explicit
@@ -266,6 +280,14 @@ cb_def_pragma (cpp_reader *pfile, unsigned int line)
{
const unsigned char *space, *name;
const cpp_token *s;
+#ifndef USE_MAPPED_LOCATION
+ location_t fe_loc;
+ const struct line_map *map = linemap_lookup (&line_table, loc);
+ fe_loc.file = map->to_file;
+ fe_loc.line = SOURCE_LINE (map, loc);
+#else
+ location_t fe_loc = loc;
+#endif
space = name = (const unsigned char *) "";
s = cpp_get_token (pfile);
@@ -277,54 +299,58 @@ cb_def_pragma (cpp_reader *pfile, unsigned int line)
name = cpp_token_as_text (pfile, s);
}
- input_line = SOURCE_LINE (map, line);
- warning ("ignoring #pragma %s %s", space, name);
+ warning (OPT_Wunknown_pragmas, "%Hignoring #pragma %s %s",
+ &fe_loc, space, name);
}
}
/* #define callback for DWARF and DWARF2 debug info. */
static void
-cb_define (cpp_reader *pfile, unsigned int line, cpp_hashnode *node)
+cb_define (cpp_reader *pfile, source_location loc, cpp_hashnode *node)
{
- (*debug_hooks->define) (SOURCE_LINE (map, line),
+ const struct line_map *map = linemap_lookup (&line_table, loc);
+ (*debug_hooks->define) (SOURCE_LINE (map, loc),
(const char *) cpp_macro_definition (pfile, node));
}
/* #undef callback for DWARF and DWARF2 debug info. */
static void
-cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, unsigned int line,
+cb_undef (cpp_reader * ARG_UNUSED (pfile), source_location loc,
cpp_hashnode *node)
{
- (*debug_hooks->undef) (SOURCE_LINE (map, line),
+ const struct line_map *map = linemap_lookup (&line_table, loc);
+ (*debug_hooks->undef) (SOURCE_LINE (map, loc),
(const char *) NODE_NAME (node));
}
-static inline const cpp_token *
-get_nonpadding_token (void)
-{
- const cpp_token *tok;
- timevar_push (TV_CPP);
- do
- tok = cpp_get_token (parse_in);
- while (tok->type == CPP_PADDING);
- timevar_pop (TV_CPP);
+/* Read a token and return its type. Fill *VALUE with its value, if
+ applicable. Fill *CPP_FLAGS with the token's flags, if it is
+ non-NULL. */
- return tok;
-}
-
-int
-c_lex_with_flags (tree *value, unsigned char *cpp_flags)
+enum cpp_ttype
+c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags)
{
- const cpp_token *tok;
- location_t atloc;
static bool no_more_pch;
+ const cpp_token *tok;
+ enum cpp_ttype type;
+ unsigned char add_flags = 0;
+ timevar_push (TV_CPP);
retry:
- tok = get_nonpadding_token ();
+ tok = cpp_get_token (parse_in);
+ type = tok->type;
retry_after_at:
- switch (tok->type)
+#ifdef USE_MAPPED_LOCATION
+ *loc = tok->src_loc;
+#else
+ *loc = input_location;
+#endif
+ switch (type)
{
+ case CPP_PADDING:
+ goto retry;
+
case CPP_NAME:
*value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node));
break;
@@ -338,9 +364,14 @@ c_lex_with_flags (tree *value, unsigned char *cpp_flags)
case CPP_N_INVALID:
/* cpplib has issued an error. */
*value = error_mark_node;
+ errorcount++;
break;
case CPP_N_INTEGER:
+ /* C++ uses '0' to mark virtual functions as pure.
+ Set PURE_ZERO to pass this information to the C++ parser. */
+ if (tok->val.str.len == 1 && *tok->val.str.text == '0')
+ add_flags = PURE_ZERO;
*value = interpret_integer (tok, flags);
break;
@@ -349,41 +380,59 @@ c_lex_with_flags (tree *value, unsigned char *cpp_flags)
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
break;
case CPP_ATSIGN:
/* An @ may give the next token special significance in Objective-C. */
- atloc = input_location;
- tok = get_nonpadding_token ();
if (c_dialect_objc ())
{
- tree val;
- switch (tok->type)
+ location_t atloc = input_location;
+
+ retry_at:
+ tok = cpp_get_token (parse_in);
+ type = tok->type;
+ switch (type)
{
- case CPP_NAME:
- val = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node));
- if (C_IS_RESERVED_WORD (val)
- && OBJC_IS_AT_KEYWORD (C_RID_CODE (val)))
- {
- *value = val;
- return CPP_AT_NAME;
- }
- break;
+ case CPP_PADDING:
+ goto retry_at;
case CPP_STRING:
case CPP_WSTRING:
- return lex_string (tok, value, true);
+ type = lex_string (tok, value, true);
+ break;
- default: break;
+ case CPP_NAME:
+ *value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node));
+ if (objc_is_reserved_word (*value))
+ {
+ type = CPP_AT_NAME;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ /* ... or not. */
+ error ("%Hstray %<@%> in program", &atloc);
+ goto retry_after_at;
}
+ break;
}
- /* ... or not. */
- error ("%Hstray '@' in program", &atloc);
- goto retry_after_at;
+ /* FALLTHROUGH */
+ case CPP_HASH:
+ case CPP_PASTE:
+ {
+ unsigned char name[4];
+
+ *cpp_spell_token (parse_in, tok, name, true) = 0;
+
+ error ("stray %qs in program", name);
+ }
+
+ goto retry;
case CPP_OTHER:
{
@@ -392,9 +441,9 @@ c_lex_with_flags (tree *value, unsigned char *cpp_flags)
if (c == '"' || c == '\'')
error ("missing terminating %c character", (int) c);
else if (ISGRAPH (c))
- error ("stray '%c' in program", (int) c);
+ error ("stray %qc in program", (int) c);
else
- error ("stray '\\%o' in program", (int) c);
+ error ("stray %<\\%o%> in program", (int) c);
}
goto retry;
@@ -405,42 +454,51 @@ c_lex_with_flags (tree *value, unsigned char *cpp_flags)
case CPP_STRING:
case CPP_WSTRING:
- return lex_string (tok, value, false);
+ if (!c_lex_return_raw_strings)
+ {
+ type = lex_string (tok, value, false);
+ break;
+ }
+ *value = build_string (tok->val.str.len, (char *) tok->val.str.text);
+ break;
+
+ case CPP_PRAGMA:
+ *value = build_int_cst (NULL, tok->val.pragma);
break;
/* These tokens should not be visible outside cpplib. */
case CPP_HEADER_NAME:
case CPP_COMMENT:
case CPP_MACRO_ARG:
- abort ();
+ gcc_unreachable ();
default:
*value = NULL_TREE;
break;
}
- if (! no_more_pch)
+ if (cpp_flags)
+ *cpp_flags = tok->flags | add_flags;
+
+ if (!no_more_pch)
{
no_more_pch = true;
c_common_no_more_pch ();
}
- if (cpp_flags)
- *cpp_flags = tok->flags;
- return tok->type;
-}
+ timevar_pop (TV_CPP);
-int
-c_lex (tree *value)
-{
- return c_lex_with_flags (value, NULL);
+ return type;
}
/* Returns the narrowest C-visible unsigned type, starting with the
- minimum specified by FLAGS, that can fit VALUE, or itk_none if
+ minimum specified by FLAGS, that can fit HIGH:LOW, or itk_none if
there isn't one. */
+
static enum integer_type_kind
-narrowest_unsigned_type (tree value, unsigned int flags)
+narrowest_unsigned_type (unsigned HOST_WIDE_INT low,
+ unsigned HOST_WIDE_INT high,
+ unsigned int flags)
{
enum integer_type_kind itk;
@@ -451,20 +509,23 @@ narrowest_unsigned_type (tree value, unsigned int flags)
else
itk = itk_unsigned_long_long;
- /* int_fits_type_p must think the type of its first argument is
- wider than its second argument, or it won't do the proper check. */
- TREE_TYPE (value) = widest_unsigned_literal_type_node;
-
for (; itk < itk_none; itk += 2 /* skip unsigned types */)
- if (int_fits_type_p (value, integer_types[itk]))
- return itk;
+ {
+ tree upper = TYPE_MAX_VALUE (integer_types[itk]);
+
+ if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (upper) > high
+ || ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (upper) == high
+ && TREE_INT_CST_LOW (upper) >= low))
+ return itk;
+ }
return itk_none;
}
/* Ditto, but narrowest signed type. */
static enum integer_type_kind
-narrowest_signed_type (tree value, unsigned int flags)
+narrowest_signed_type (unsigned HOST_WIDE_INT low,
+ unsigned HOST_WIDE_INT high, unsigned int flags)
{
enum integer_type_kind itk;
@@ -475,13 +536,16 @@ narrowest_signed_type (tree value, unsigned int flags)
else
itk = itk_long_long;
- /* int_fits_type_p must think the type of its first argument is
- wider than its second argument, or it won't do the proper check. */
- TREE_TYPE (value) = widest_unsigned_literal_type_node;
for (; itk < itk_none; itk += 2 /* skip signed types */)
- if (int_fits_type_p (value, integer_types[itk]))
- return itk;
+ {
+ tree upper = TYPE_MAX_VALUE (integer_types[itk]);
+
+ if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (upper) > high
+ || ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (upper) == high
+ && TREE_INT_CST_LOW (upper) >= low))
+ return itk;
+ }
return itk_none;
}
@@ -497,18 +561,19 @@ interpret_integer (const cpp_token *token, unsigned int flags)
integer = cpp_interpret_integer (parse_in, token, flags);
integer = cpp_num_sign_extend (integer, options->precision);
- value = build_int_2_wide (integer.low, integer.high);
/* The type of a constant with a U suffix is straightforward. */
if (flags & CPP_N_UNSIGNED)
- itk = narrowest_unsigned_type (value, flags);
+ itk = narrowest_unsigned_type (integer.low, integer.high, flags);
else
{
/* The type of a potentially-signed integer constant varies
depending on the base it's in, the standard in use, and the
length suffixes. */
- enum integer_type_kind itk_u = narrowest_unsigned_type (value, flags);
- enum integer_type_kind itk_s = narrowest_signed_type (value, flags);
+ enum integer_type_kind itk_u
+ = narrowest_unsigned_type (integer.low, integer.high, flags);
+ enum integer_type_kind itk_s
+ = narrowest_signed_type (integer.low, integer.high, flags);
/* In both C89 and C99, octal and hex constants may be signed or
unsigned, whichever fits tighter. We do not warn about this
@@ -532,10 +597,11 @@ interpret_integer (const cpp_token *token, unsigned int flags)
if (itk_u < itk_unsigned_long)
itk_u = itk_unsigned_long;
itk = itk_u;
- warning ("this decimal constant is unsigned only in ISO C90");
+ warning (0, "this decimal constant is unsigned only in ISO C90");
}
- else if (warn_traditional)
- warning ("this decimal constant would be unsigned in ISO C90");
+ else
+ warning (OPT_Wtraditional,
+ "this decimal constant would be unsigned in ISO C90");
}
}
}
@@ -550,15 +616,15 @@ interpret_integer (const cpp_token *token, unsigned int flags)
if (itk > itk_unsigned_long
&& (flags & CPP_N_WIDTH) != CPP_N_LARGE
- && ! in_system_header && ! flag_isoc99)
- pedwarn ("integer constant is too large for \"%s\" type",
+ && !in_system_header && !flag_isoc99)
+ pedwarn ("integer constant is too large for %qs type",
(flags & CPP_N_UNSIGNED) ? "unsigned long" : "long");
- TREE_TYPE (value) = type;
+ value = build_int_cst_wide (type, integer.low, integer.high);
/* Convert imaginary to a complex type. */
if (flags & CPP_N_IMAGINARY)
- value = build_complex (NULL_TREE, convert (type, integer_zero_node), value);
+ value = build_complex (NULL_TREE, build_int_cst (type, 0), value);
return value;
}
@@ -573,51 +639,53 @@ interpret_float (const cpp_token *token, unsigned int flags)
REAL_VALUE_TYPE real;
char *copy;
size_t copylen;
- const char *typename;
- /* FIXME: make %T work in error/warning, then we don't need typename. */
- if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
- {
+ /* Decode type based on width and properties. */
+ if (flags & CPP_N_DFLOAT)
+ if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ type = dfloat128_type_node;
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ type = dfloat32_type_node;
+ else
+ type = dfloat64_type_node;
+ else
+ if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
type = long_double_type_node;
- typename = "long double";
- }
- else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
- || flag_single_precision_constant)
- {
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
+ || flag_single_precision_constant)
type = float_type_node;
- typename = "float";
- }
- else
- {
+ else
type = double_type_node;
- typename = "double";
- }
/* Copy the constant to a nul-terminated buffer. If the constant
has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF
can't handle them. */
copylen = token->val.str.len;
- if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM)
- /* Must be an F or L suffix. */
- copylen--;
- if (flags & CPP_N_IMAGINARY)
- /* I or J suffix. */
- copylen--;
+ if (flags & CPP_N_DFLOAT)
+ copylen -= 2;
+ else
+ {
+ if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM)
+ /* Must be an F or L suffix. */
+ copylen--;
+ if (flags & CPP_N_IMAGINARY)
+ /* I or J suffix. */
+ copylen--;
+ }
- copy = alloca (copylen + 1);
+ copy = (char *) alloca (copylen + 1);
memcpy (copy, token->val.str.text, copylen);
copy[copylen] = '\0';
- real_from_string (&real, copy);
- real_convert (&real, TYPE_MODE (type), &real);
+ real_from_string3 (&real, copy, TYPE_MODE (type));
- /* A diagnostic is required for "soft" overflow by some ISO C
- testsuites. This is not pedwarn, because some people don't want
- an error for this.
- ??? That's a dubious reason... is this a mandatory diagnostic or
- isn't it? -- zw, 2001-08-21. */
+ /* Both C and C++ require a diagnostic for a floating constant
+ outside the range of representable values of its type. Since we
+ have __builtin_inf* to produce an infinity, it might now be
+ appropriate for this to be a mandatory pedwarn rather than
+ conditioned on -pedantic. */
if (REAL_VALUE_ISINF (real) && pedantic)
- warning ("floating constant exceeds range of \"%s\"", typename);
+ pedwarn ("floating constant exceeds range of %qT", type);
/* Create a node with determined type and value. */
value = build_real (type, real);
@@ -648,7 +716,7 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string)
{
tree value;
bool wide = false;
- size_t count = 1;
+ size_t concats = 0;
struct obstack str_ob;
cpp_string istr;
@@ -660,45 +728,76 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string)
if (tok->type == CPP_WSTRING)
wide = true;
- tok = get_nonpadding_token ();
- if (c_dialect_objc () && tok->type == CPP_ATSIGN)
- {
- objc_string = true;
- tok = get_nonpadding_token ();
- }
- if (tok->type == CPP_STRING || tok->type == CPP_WSTRING)
+ retry:
+ tok = cpp_get_token (parse_in);
+ switch (tok->type)
{
- gcc_obstack_init (&str_ob);
- obstack_grow (&str_ob, &str, sizeof (cpp_string));
+ case CPP_PADDING:
+ goto retry;
+ case CPP_ATSIGN:
+ if (c_dialect_objc ())
+ {
+ objc_string = true;
+ goto retry;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ break;
- do
+ case CPP_WSTRING:
+ wide = true;
+ /* FALLTHROUGH */
+
+ case CPP_STRING:
+ if (!concats)
{
- count++;
- if (tok->type == CPP_WSTRING)
- wide = true;
- obstack_grow (&str_ob, &tok->val.str, sizeof (cpp_string));
-
- tok = get_nonpadding_token ();
- if (c_dialect_objc () && tok->type == CPP_ATSIGN)
- {
- objc_string = true;
- tok = get_nonpadding_token ();
- }
+ gcc_obstack_init (&str_ob);
+ obstack_grow (&str_ob, &str, sizeof (cpp_string));
}
- while (tok->type == CPP_STRING || tok->type == CPP_WSTRING);
- strs = obstack_finish (&str_ob);
+
+ concats++;
+ obstack_grow (&str_ob, &tok->val.str, sizeof (cpp_string));
+ goto retry;
}
/* We have read one more token than we want. */
_cpp_backup_tokens (parse_in, 1);
+ if (concats)
+ strs = XOBFINISH (&str_ob, cpp_string *);
- if (count > 1 && !objc_string && warn_traditional && !in_system_header)
- warning ("traditional C rejects string constant concatenation");
+ if (concats && !objc_string && !in_system_header)
+ warning (OPT_Wtraditional,
+ "traditional C rejects string constant concatenation");
- if (cpp_interpret_string (parse_in, strs, count, &istr, wide))
+ if ((c_lex_string_translate
+ ? cpp_interpret_string : cpp_interpret_string_notranslate)
+ (parse_in, strs, concats + 1, &istr, wide))
{
- value = build_string (istr.len, (char *)istr.text);
- free ((void *)istr.text);
+ value = build_string (istr.len, (char *) istr.text);
+ free ((void *) istr.text);
+
+ if (c_lex_string_translate == -1)
+ {
+ int xlated = cpp_interpret_string_notranslate (parse_in, strs,
+ concats + 1,
+ &istr, wide);
+ /* Assume that, if we managed to translate the string above,
+ then the untranslated parsing will always succeed. */
+ gcc_assert (xlated);
+
+ if (TREE_STRING_LENGTH (value) != (int) istr.len
+ || 0 != strncmp (TREE_STRING_POINTER (value), (char *) istr.text,
+ istr.len))
+ {
+ /* Arrange for us to return the untranslated string in
+ *valp, but to set up the C type of the translated
+ one. */
+ *valp = build_string (istr.len, (char *) istr.text);
+ valp = &TREE_CHAIN (*valp);
+ }
+ free ((void *) istr.text);
+ }
}
else
{
@@ -717,7 +816,7 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string)
TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
*valp = fix_string_type (value);
- if (strs != &str)
+ if (concats)
obstack_free (&str_ob, 0);
return objc_string ? CPP_OBJC_STRING : wide ? CPP_WSTRING : CPP_STRING;
@@ -735,13 +834,6 @@ lex_charconst (const cpp_token *token)
result = cpp_interpret_charconst (parse_in, token,
&chars_seen, &unsignedp);
- /* Cast to cppchar_signed_t to get correct sign-extension of RESULT
- before possibly widening to HOST_WIDE_INT for build_int_2. */
- if (unsignedp || (cppchar_signed_t) result >= 0)
- value = build_int_2 (result, 0);
- else
- value = build_int_2 ((cppchar_signed_t) result, -1);
-
if (token->type == CPP_WCHAR)
type = wchar_type_node;
/* In C, a character constant has type 'int'.
@@ -751,6 +843,12 @@ lex_charconst (const cpp_token *token)
else
type = char_type_node;
- TREE_TYPE (value) = type;
+ /* Cast to cppchar_signed_t to get correct sign-extension of RESULT
+ before possibly widening to HOST_WIDE_INT for build_int_cst. */
+ if (unsignedp || (cppchar_signed_t) result >= 0)
+ value = build_int_cst_wide (type, result, 0);
+ else
+ value = build_int_cst_wide (type, (cppchar_signed_t) result, -1);
+
return value;
}
diff --git a/contrib/gcc/c-opts.c b/contrib/gcc/c-opts.c
index 84f86cb..d27959f 100644
--- a/contrib/gcc/c-opts.c
+++ b/contrib/gcc/c-opts.c
@@ -1,5 +1,6 @@
/* C/ObjC/C++ command line option handling.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Neil Booth.
This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* $FreeBSD$ */
@@ -39,6 +40,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "debug.h" /* For debug_hooks. */
#include "opts.h"
#include "options.h"
+#include "mkdeps.h"
#ifndef DOLLARS_IN_IDENTIFIERS
# define DOLLARS_IN_IDENTIFIERS true
@@ -48,7 +50,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
# define TARGET_SYSTEM_ROOT NULL
#endif
-static int saved_lineno;
+#ifndef TARGET_OPTF
+#define TARGET_OPTF(ARG)
+#endif
/* CPP's options. */
static cpp_options *cpp_opts;
@@ -69,12 +73,18 @@ static bool deps_seen;
/* If -v seen. */
static bool verbose;
+/* If -lang-fortran seen. */
+static bool lang_fortran = false;
+
/* Dependency output file. */
static const char *deps_file;
/* The prefix given by -iprefix, if any. */
static const char *iprefix;
+/* The multilib directory given by -imultilib, if any. */
+static const char *imultilib;
+
/* The system root, if any. Overridden by -isysroot. */
static const char *sysroot = TARGET_SYSTEM_ROOT;
@@ -90,15 +100,15 @@ static bool quote_chain_split;
/* If -Wunused-macros. */
static bool warn_unused_macros;
+/* If -Wvariadic-macros. */
+static bool warn_variadic_macros = true;
+
/* Number of deferred options. */
static size_t deferred_count;
/* Number of deferred options scanned for -include. */
static size_t include_cursor;
-/* Permit Fotran front-end options. */
-static bool permit_fortran_options;
-
static void set_Wimplicit (int);
static void handle_OPT_d (const char *);
static void set_std_cxx98 (int);
@@ -140,23 +150,25 @@ c_common_missing_argument (const char *opt, size_t code)
return false;
case OPT_fconstant_string_class_:
- error ("no class name specified with \"%s\"", opt);
+ error ("no class name specified with %qs", opt);
break;
case OPT_A:
- error ("assertion missing after \"%s\"", opt);
+ error ("assertion missing after %qs", opt);
break;
case OPT_D:
case OPT_U:
- error ("macro name missing after \"%s\"", opt);
+ error ("macro name missing after %qs", opt);
break;
+ case OPT_F:
case OPT_I:
case OPT_idirafter:
case OPT_isysroot:
case OPT_isystem:
- error ("missing path after \"%s\"", opt);
+ case OPT_iquote:
+ error ("missing path after %qs", opt);
break;
case OPT_MF:
@@ -165,12 +177,12 @@ c_common_missing_argument (const char *opt, size_t code)
case OPT_include:
case OPT_imacros:
case OPT_o:
- error ("missing filename after \"%s\"", opt);
+ error ("missing filename after %qs", opt);
break;
case OPT_MQ:
case OPT_MT:
- error ("missing makefile target after \"%s\"", opt);
+ error ("missing makefile target after %qs", opt);
break;
}
@@ -206,7 +218,7 @@ c_common_init_options (unsigned int argc, const char **argv)
}
parse_in = cpp_create_reader (c_dialect_cxx () ? CLK_GNUCXX: CLK_GNUC89,
- ident_hash);
+ ident_hash, &line_table);
cpp_opts = cpp_get_options (parse_in);
cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
@@ -216,33 +228,35 @@ c_common_init_options (unsigned int argc, const char **argv)
before passing on command-line options to cpplib. */
cpp_opts->warn_dollars = 0;
- flag_const_strings = c_dialect_cxx ();
flag_exceptions = c_dialect_cxx ();
warn_pointer_arith = c_dialect_cxx ();
+ warn_write_strings = c_dialect_cxx();
- deferred_opts = xmalloc (argc * sizeof (struct deferred_opt));
+ deferred_opts = XNEWVEC (struct deferred_opt, argc);
result = lang_flags[c_language];
if (c_language == clk_c)
{
+ /* If preprocessing assembly language, accept any of the C-family
+ front end options since the driver may pass them through. */
for (i = 1; i < argc; i++)
- {
- /* If preprocessing assembly language, accept any of the C-family
- front end options since the driver may pass them through. */
- if (! strcmp (argv[i], "-lang-asm"))
+ if (! strcmp (argv[i], "-lang-asm"))
+ {
result |= CL_C | CL_ObjC | CL_CXX | CL_ObjCXX;
-#ifdef CL_F77
- /* If potentially preprocessing Fortran we have to accept its
- front end options since the driver may them through. */
- else if (! strcmp (argv[i], "-traditional-cpp"))
- {
- permit_fortran_options = true;
- result |= CL_F77;
- }
-#endif
+ break;
+ }
+
+#ifdef CL_Fortran
+ for (i = 1; i < argc; i++)
+ if (! strcmp (argv[i], "-lang-fortran"))
+ {
+ result |= CL_Fortran;
+ break;
}
+#endif
}
+
return result;
}
@@ -257,10 +271,20 @@ c_common_handle_option (size_t scode, const char *arg, int value)
enum opt_code code = (enum opt_code) scode;
int result = 1;
+ /* Prevent resetting the language standard to a C dialect when the driver
+ has already determined that we're looking at assembler input. */
+ bool preprocessing_asm_p = (cpp_get_options (parse_in)->lang == CLK_ASM);
+
switch (code)
{
default:
- result = permit_fortran_options;
+ if (cl_options[code].flags & (CL_C | CL_CXX | CL_ObjC | CL_ObjCXX))
+ break;
+#ifdef CL_Fortran
+ if (lang_fortran && (cl_options[code].flags & (CL_Fortran)))
+ break;
+#endif
+ result = 0;
break;
case OPT__output_pch_:
@@ -292,15 +316,20 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->print_include_names = 1;
break;
+ case OPT_F:
+ TARGET_OPTF (xstrdup (arg));
+ break;
+
case OPT_I:
if (strcmp (arg, "-"))
- add_path (xstrdup (arg), BRACKET, 0);
+ add_path (xstrdup (arg), BRACKET, 0, true);
else
{
if (quote_chain_split)
error ("-I- specified twice");
quote_chain_split = true;
split_quote_chain ();
+ inform ("obsolete option -I- used, please use -iquote instead");
}
break;
@@ -354,10 +383,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
defer_opt (code, arg);
break;
- case OPT_Wabi:
- warn_abi = value;
- break;
-
case OPT_Wall:
set_Wunused (value);
set_Wformat (value);
@@ -371,6 +396,8 @@ c_common_handle_option (size_t scode, const char *arg, int value)
warn_sign_compare = value;
warn_switch = value;
warn_strict_aliasing = value;
+ warn_strict_overflow = value;
+ warn_address = value;
/* Only warn about unknown pragmas that are not in system
headers. */
@@ -389,7 +416,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
else
{
/* C++-specific warnings. */
- warn_nonvdtor = value;
warn_reorder = value;
warn_nontemplate_friend = value;
}
@@ -398,18 +424,9 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->warn_comments = value;
cpp_opts->warn_num_sign_change = value;
cpp_opts->warn_multichar = value; /* Was C++ only. */
- break;
-
- case OPT_Wbad_function_cast:
- warn_bad_function_cast = value;
- break;
- case OPT_Wcast_qual:
- warn_cast_qual = value;
- break;
-
- case OPT_Wchar_subscripts:
- warn_char_subscripts = value;
+ if (warn_pointer_sign == -1)
+ warn_pointer_sign = 1;
break;
case OPT_Wcomment:
@@ -417,47 +434,23 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->warn_comments = value;
break;
- case OPT_Wconversion:
- warn_conversion = value;
- break;
-
- case OPT_Wctor_dtor_privacy:
- warn_ctor_dtor_privacy = value;
- break;
-
- case OPT_Wdeclaration_after_statement:
- warn_declaration_after_statement = value;
- break;
-
case OPT_Wdeprecated:
- warn_deprecated = value;
cpp_opts->warn_deprecated = value;
break;
- case OPT_Wdiv_by_zero:
- warn_div_by_zero = value;
- break;
-
- case OPT_Weffc__:
- warn_ecpp = value;
- break;
-
case OPT_Wendif_labels:
cpp_opts->warn_endif_labels = value;
break;
case OPT_Werror:
cpp_opts->warnings_are_errors = value;
+ global_dc->warning_as_error_requested = value;
break;
case OPT_Werror_implicit_function_declaration:
mesg_implicit_function_declaration = 2;
break;
- case OPT_Wfloat_equal:
- warn_float_equal = value;
- break;
-
case OPT_Wformat:
set_Wformat (value);
break;
@@ -466,58 +459,18 @@ c_common_handle_option (size_t scode, const char *arg, int value)
set_Wformat (atoi (arg));
break;
- case OPT_Wformat_extra_args:
- warn_format_extra_args = value;
- break;
-
- case OPT_Wformat_nonliteral:
- warn_format_nonliteral = value;
- break;
-
- case OPT_Wformat_security:
- warn_format_security = value;
- break;
-
- case OPT_Wformat_y2k:
- warn_format_y2k = value;
- break;
-
- case OPT_Wformat_zero_length:
- warn_format_zero_length = value;
- break;
-
- case OPT_Winit_self:
- warn_init_self = value;
- break;
-
case OPT_Wimplicit:
set_Wimplicit (value);
break;
- case OPT_Wimplicit_function_declaration:
- mesg_implicit_function_declaration = value;
- break;
-
- case OPT_Wimplicit_int:
- warn_implicit_int = value;
- break;
-
case OPT_Wimport:
/* Silently ignore for now. */
break;
- case OPT_Winvalid_offsetof:
- warn_invalid_offsetof = value;
- break;
-
case OPT_Winvalid_pch:
cpp_opts->warn_invalid_pch = value;
break;
- case OPT_Wlong_long:
- warn_long_long = value;
- break;
-
case OPT_Wmain:
if (value)
warn_main = 1;
@@ -525,104 +478,33 @@ c_common_handle_option (size_t scode, const char *arg, int value)
warn_main = -1;
break;
- case OPT_Wmissing_braces:
- warn_missing_braces = value;
- break;
-
- case OPT_Wmissing_declarations:
- warn_missing_declarations = value;
- break;
-
- case OPT_Wmissing_format_attribute:
- warn_missing_format_attribute = value;
- break;
-
- case OPT_Wmissing_prototypes:
- warn_missing_prototypes = value;
+ case OPT_Wmissing_include_dirs:
+ cpp_opts->warn_missing_include_dirs = value;
break;
case OPT_Wmultichar:
cpp_opts->warn_multichar = value;
break;
- case OPT_Wnested_externs:
- warn_nested_externs = value;
- break;
-
- case OPT_Wnon_template_friend:
- warn_nontemplate_friend = value;
- break;
-
- case OPT_Wnon_virtual_dtor:
- warn_nonvdtor = value;
- break;
-
- case OPT_Wnonnull:
- warn_nonnull = value;
- break;
-
- case OPT_Wold_style_definition:
- warn_old_style_definition = value;
- break;
-
- case OPT_Wold_style_cast:
- warn_old_style_cast = value;
- break;
-
- case OPT_Woverloaded_virtual:
- warn_overloaded_virtual = value;
- break;
-
- case OPT_Wparentheses:
- warn_parentheses = value;
- break;
-
- case OPT_Wpmf_conversions:
- warn_pmf2ptr = value;
- break;
-
- case OPT_Wpointer_arith:
- warn_pointer_arith = value;
- break;
-
- case OPT_Wprotocol:
- warn_protocol = value;
- break;
-
- case OPT_Wselector:
- warn_selector = value;
- break;
-
- case OPT_Wredundant_decls:
- warn_redundant_decls = value;
- break;
-
- case OPT_Wreorder:
- warn_reorder = value;
+ case OPT_Wnormalized_:
+ if (!value || (arg && strcasecmp (arg, "none") == 0))
+ cpp_opts->warn_normalize = normalized_none;
+ else if (!arg || strcasecmp (arg, "nfkc") == 0)
+ cpp_opts->warn_normalize = normalized_KC;
+ else if (strcasecmp (arg, "id") == 0)
+ cpp_opts->warn_normalize = normalized_identifier_C;
+ else if (strcasecmp (arg, "nfc") == 0)
+ cpp_opts->warn_normalize = normalized_C;
+ else
+ error ("argument %qs to %<-Wnormalized%> not recognized", arg);
break;
case OPT_Wreturn_type:
warn_return_type = value;
break;
- case OPT_Wsequence_point:
- warn_sequence_point = value;
- break;
-
- case OPT_Wsign_compare:
- warn_sign_compare = value;
- break;
-
- case OPT_Wsign_promo:
- warn_sign_promo = value;
- break;
-
- case OPT_Wstrict_prototypes:
- warn_strict_prototypes = value;
- break;
-
- case OPT_Wsynth:
- warn_synth = value;
+ case OPT_Wstrict_null_sentinel:
+ warn_strict_null_sentinel = value;
break;
case OPT_Wsystem_headers:
@@ -630,7 +512,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
break;
case OPT_Wtraditional:
- warn_traditional = value;
cpp_opts->warn_traditional = value;
break;
@@ -638,10 +519,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->warn_trigraphs = value;
break;
- case OPT_Wundeclared_selector:
- warn_undeclared_selector = value;
- break;
-
case OPT_Wundef:
cpp_opts->warn_undef = value;
break;
@@ -656,11 +533,18 @@ c_common_handle_option (size_t scode, const char *arg, int value)
warn_unused_macros = value;
break;
+ case OPT_Wvariadic_macros:
+ warn_variadic_macros = value;
+ break;
+
case OPT_Wwrite_strings:
- if (!c_dialect_cxx ())
- flag_const_strings = value;
- else
- warn_write_strings = value;
+ warn_write_strings = value;
+ break;
+
+ case OPT_Weffc__:
+ warn_ecpp = value;
+ if (value)
+ warn_nonvdtor = true;
break;
case OPT_ansi:
@@ -699,7 +583,7 @@ c_common_handle_option (size_t scode, const char *arg, int value)
case OPT_fvtable_thunks:
case OPT_fxref:
case OPT_fvtable_gc:
- warning ("switch \"%s\" is no longer supported", option->opt_text);
+ warning (0, "switch %qs is no longer supported", option->opt_text);
break;
case OPT_faccess_control:
@@ -725,11 +609,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->dollars_in_ident = value;
break;
- case OPT_fdump_:
- if (!dump_switch_p (arg))
- result = 0;
- break;
-
case OPT_ffreestanding:
value = !value;
/* Fall through.... */
@@ -755,7 +634,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
case OPT_fsigned_bitfields:
flag_signed_bitfields = value;
- explicit_flag_signed_bitfields = 1;
break;
case OPT_fsigned_char:
@@ -764,7 +642,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
case OPT_funsigned_bitfields:
flag_signed_bitfields = !value;
- explicit_flag_signed_bitfields = 1;
break;
case OPT_funsigned_char:
@@ -779,10 +656,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
flag_conserve_space = value;
break;
- case OPT_fconst_strings:
- flag_const_strings = value;
- break;
-
case OPT_fconstant_string_class_:
constant_string_class_name = arg;
break;
@@ -799,11 +672,8 @@ c_common_handle_option (size_t scode, const char *arg, int value)
flag_enforce_eh_specs = value;
break;
- case OPT_ffixed_form:
- case OPT_ffixed_line_length_:
- /* Fortran front end options ignored when preprocessing only. */
- if (!flag_preprocess_only)
- result = 0;
+ case OPT_fextended_identifiers:
+ cpp_opts->extended_identifiers = value;
break;
case OPT_ffor_scope:
@@ -819,7 +689,7 @@ c_common_handle_option (size_t scode, const char *arg, int value)
break;
case OPT_fhandle_exceptions:
- warning ("-fhandle-exceptions has been renamed -fexceptions (and is now on by default)");
+ warning (0, "-fhandle-exceptions has been renamed -fexceptions (and is now on by default)");
flag_exceptions = value;
break;
@@ -851,10 +721,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
flag_no_nonansi_builtin = !value;
break;
- case OPT_fobjc_exceptions:
- flag_objc_exceptions = value;
- break;
-
case OPT_foperator_names:
cpp_opts->operator_names = value;
break;
@@ -867,6 +733,10 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->restore_pch_deps = value;
break;
+ case OPT_fpch_preprocess:
+ flag_pch_preprocess = value;
+ break;
+
case OPT_fpermissive:
flag_permissive = value;
break;
@@ -878,7 +748,7 @@ c_common_handle_option (size_t scode, const char *arg, int value)
case OPT_freplace_objc_classes:
flag_replace_objc_classes = value;
break;
-
+
case OPT_frepo:
flag_use_repository = value;
if (value)
@@ -922,11 +792,23 @@ c_common_handle_option (size_t scode, const char *arg, int value)
case OPT_fuse_cxa_atexit:
flag_use_cxa_atexit = value;
break;
+
+ case OPT_fuse_cxa_get_exception_ptr:
+ flag_use_cxa_get_exception_ptr = value;
+ break;
+
+ case OPT_fvisibility_inlines_hidden:
+ visibility_options.inlines_hidden = value;
+ break;
case OPT_fweak:
flag_weak = value;
break;
+ case OPT_fthreadsafe_statics:
+ flag_threadsafe_statics = value;
+ break;
+
case OPT_fzero_link:
flag_zero_link = value;
break;
@@ -936,7 +818,7 @@ c_common_handle_option (size_t scode, const char *arg, int value)
break;
case OPT_idirafter:
- add_path (xstrdup (arg), AFTER, 0);
+ add_path (xstrdup (arg), AFTER, 0, true);
break;
case OPT_imacros:
@@ -944,16 +826,24 @@ c_common_handle_option (size_t scode, const char *arg, int value)
defer_opt (code, arg);
break;
+ case OPT_imultilib:
+ imultilib = arg;
+ break;
+
case OPT_iprefix:
iprefix = arg;
break;
+ case OPT_iquote:
+ add_path (xstrdup (arg), QUOTE, 0, true);
+ break;
+
case OPT_isysroot:
sysroot = arg;
break;
case OPT_isystem:
- add_path (xstrdup (arg), SYSTEM, 0);
+ add_path (xstrdup (arg), SYSTEM, 0, true);
break;
case OPT_iwithprefix:
@@ -969,6 +859,10 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->dollars_in_ident = false;
break;
+ case OPT_lang_fortran:
+ lang_fortran = true;
+ break;
+
case OPT_lang_objc:
cpp_opts->objc = 1;
break;
@@ -997,41 +891,55 @@ c_common_handle_option (size_t scode, const char *arg, int value)
case OPT_pedantic:
cpp_opts->pedantic = 1;
cpp_opts->warn_endif_labels = 1;
+ if (warn_pointer_sign == -1)
+ warn_pointer_sign = 1;
+ if (warn_overlength_strings == -1)
+ warn_overlength_strings = 1;
break;
case OPT_print_objc_runtime_info:
print_struct_values = 1;
break;
+ case OPT_print_pch_checksum:
+ c_common_print_pch_checksum (stdout);
+ exit_after_options = true;
+ break;
+
case OPT_remap:
cpp_opts->remap = 1;
break;
case OPT_std_c__98:
case OPT_std_gnu__98:
- set_std_cxx98 (code == OPT_std_c__98 /* ISO */);
+ if (!preprocessing_asm_p)
+ set_std_cxx98 (code == OPT_std_c__98 /* ISO */);
break;
case OPT_std_c89:
case OPT_std_iso9899_1990:
case OPT_std_iso9899_199409:
- set_std_c89 (code == OPT_std_iso9899_199409 /* c94 */, true /* ISO */);
+ if (!preprocessing_asm_p)
+ set_std_c89 (code == OPT_std_iso9899_199409 /* c94 */, true /* ISO */);
break;
case OPT_std_gnu89:
- set_std_c89 (false /* c94 */, false /* ISO */);
+ if (!preprocessing_asm_p)
+ set_std_c89 (false /* c94 */, false /* ISO */);
break;
case OPT_std_c99:
case OPT_std_c9x:
case OPT_std_iso9899_1999:
case OPT_std_iso9899_199x:
- set_std_c99 (true /* ISO */);
+ if (!preprocessing_asm_p)
+ set_std_c99 (true /* ISO */);
break;
case OPT_std_gnu99:
case OPT_std_gnu9x:
- set_std_c99 (false /* ISO */);
+ if (!preprocessing_asm_p)
+ set_std_c99 (false /* ISO */);
break;
case OPT_trigraphs:
@@ -1053,9 +961,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
case OPT_v:
verbose = true;
break;
-
- case OPT_fformat_extensions:
- break;
}
return result;
@@ -1070,7 +975,7 @@ c_common_post_options (const char **pfilename)
/* Canonicalize the input and output filenames. */
if (in_fnames == NULL)
{
- in_fnames = xmalloc (sizeof (in_fnames[0]));
+ in_fnames = XNEWVEC (const char *, 1);
in_fnames[0] = "";
}
else if (strcmp (in_fnames[0], "-") == 0)
@@ -1086,48 +991,80 @@ c_common_post_options (const char **pfilename)
sanitize_cpp_opts ();
- register_include_chains (parse_in, sysroot, iprefix,
+ register_include_chains (parse_in, sysroot, iprefix, imultilib,
std_inc, std_cxx_inc && c_dialect_cxx (), verbose);
- flag_inline_trees = 1;
+#ifdef C_COMMON_OVERRIDE_OPTIONS
+ /* Some machines may reject certain combinations of C
+ language-specific options. */
+ C_COMMON_OVERRIDE_OPTIONS;
+#endif
- /* Use tree inlining if possible. Function instrumentation is only
- done in the RTL level, so we disable tree inlining. */
- if (flag_instrument_function_entry_exit)
- {
- flag_no_inline = 1;
- flag_really_no_inline = 1;
- }
- else
- {
- if (!flag_no_inline)
- flag_no_inline = 1;
- if (flag_inline_functions)
- {
- flag_inline_trees = 2;
- flag_inline_functions = 0;
- }
- }
+ flag_inline_trees = 1;
- /* -Wextra implies -Wsign-compare, but not if explicitly
- overridden. */
+ /* Use tree inlining. */
+ if (!flag_no_inline)
+ flag_no_inline = 1;
+ if (flag_inline_functions)
+ flag_inline_trees = 2;
+
+ /* We recognize -fgnu89-inline in preparation for 4.3 where the
+ option will be meaningful. Here we just reject
+ -fno-gnu89-inline, since we don't support it. */
+ if (!flag_gnu89_inline)
+ error ("-fno-gnu89-inline is not supported");
+
+ /* If we are given more than one input file, we must use
+ unit-at-a-time mode. */
+ if (num_in_fnames > 1)
+ flag_unit_at_a_time = 1;
+
+ /* Default to ObjC sjlj exception handling if NeXT runtime. */
+ if (flag_objc_sjlj_exceptions < 0)
+ flag_objc_sjlj_exceptions = flag_next_runtime;
+ if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
+ flag_exceptions = 1;
+
+ /* -Wextra implies -Wsign-compare, -Wmissing-field-initializers and
+ -Woverride-init, but not if explicitly overridden. */
if (warn_sign_compare == -1)
warn_sign_compare = extra_warnings;
+ if (warn_missing_field_initializers == -1)
+ warn_missing_field_initializers = extra_warnings;
+ if (warn_override_init == -1)
+ warn_override_init = extra_warnings;
+
+ /* -Wpointer_sign is disabled by default, but it is enabled if any
+ of -Wall or -pedantic are given. */
+ if (warn_pointer_sign == -1)
+ warn_pointer_sign = 0;
+
+ /* -Woverlength-strings is off by default, but is enabled by -pedantic.
+ It is never enabled in C++, as the minimum limit is not normative
+ in that standard. */
+ if (warn_overlength_strings == -1 || c_dialect_cxx ())
+ warn_overlength_strings = 0;
/* Special format checking options don't work without -Wformat; warn if
they are used. */
- if (warn_format_y2k && !warn_format)
- warning ("-Wformat-y2k ignored without -Wformat");
- if (warn_format_extra_args && !warn_format)
- warning ("-Wformat-extra-args ignored without -Wformat");
- if (warn_format_zero_length && !warn_format)
- warning ("-Wformat-zero-length ignored without -Wformat");
- if (warn_format_nonliteral && !warn_format)
- warning ("-Wformat-nonliteral ignored without -Wformat");
- if (warn_format_security && !warn_format)
- warning ("-Wformat-security ignored without -Wformat");
- if (warn_missing_format_attribute && !warn_format)
- warning ("-Wmissing-format-attribute ignored without -Wformat");
+ if (!warn_format)
+ {
+ warning (OPT_Wformat_y2k,
+ "-Wformat-y2k ignored without -Wformat");
+ warning (OPT_Wformat_extra_args,
+ "-Wformat-extra-args ignored without -Wformat");
+ warning (OPT_Wformat_zero_length,
+ "-Wformat-zero-length ignored without -Wformat");
+ warning (OPT_Wformat_nonliteral,
+ "-Wformat-nonliteral ignored without -Wformat");
+ warning (OPT_Wformat_security,
+ "-Wformat-security ignored without -Wformat");
+ }
+
+ /* C99 requires special handling of complex multiplication and division;
+ -ffast-math and -fcx-limited-range are handled in process_options. */
+ if (flag_isoc99)
+ flag_complex_method = 2;
if (flag_preprocess_only)
{
@@ -1156,7 +1093,7 @@ c_common_post_options (const char **pfilename)
init_c_lex ();
/* Yuk. WTF is this? I do know ObjC relies on it somewhere. */
- input_line = 0;
+ input_location = UNKNOWN_LOCATION;
}
cb = cpp_get_callbacks (parse_in);
@@ -1164,8 +1101,7 @@ c_common_post_options (const char **pfilename)
cb->dir_change = cb_dir_change;
cpp_post_options (parse_in);
- saved_lineno = input_line;
- input_line = 0;
+ input_location = UNKNOWN_LOCATION;
/* If an error has occurred in cpplib, note it so we fail
immediately. */
@@ -1181,7 +1117,7 @@ c_common_post_options (const char **pfilename)
}
if (flag_working_directory
- && flag_preprocess_only && ! flag_no_line_commands)
+ && flag_preprocess_only && !flag_no_line_commands)
pp_dir_change (parse_in, get_src_pwd ());
return flag_preprocess_only;
@@ -1191,21 +1127,22 @@ c_common_post_options (const char **pfilename)
bool
c_common_init (void)
{
- input_line = saved_lineno;
-
/* Set up preprocessor arithmetic. Must be done after call to
c_common_nodes_and_builtins for type nodes to be good. */
cpp_opts->precision = TYPE_PRECISION (intmax_type_node);
cpp_opts->char_precision = TYPE_PRECISION (char_type_node);
cpp_opts->int_precision = TYPE_PRECISION (integer_type_node);
cpp_opts->wchar_precision = TYPE_PRECISION (wchar_type_node);
- cpp_opts->unsigned_wchar = TREE_UNSIGNED (wchar_type_node);
+ cpp_opts->unsigned_wchar = TYPE_UNSIGNED (wchar_type_node);
cpp_opts->bytes_big_endian = BYTES_BIG_ENDIAN;
/* This can't happen until after wchar_precision and bytes_big_endian
are known. */
cpp_init_iconv (parse_in);
+ if (version_flag)
+ c_common_print_pch_checksum (stderr);
+
if (flag_preprocess_only)
{
finish_options ();
@@ -1222,41 +1159,44 @@ c_common_init (void)
/* Initialize the integrated preprocessor after debug output has been
initialized; loop over each input file. */
void
-c_common_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
+c_common_parse_file (int set_yydebug)
{
- unsigned file_index;
-
+ unsigned int i;
+
+ /* Enable parser debugging, if requested and we can. If requested
+ and we can't, notify the user. */
#if YYDEBUG != 0
yydebug = set_yydebug;
#else
- warning ("YYDEBUG not defined");
+ if (set_yydebug)
+ warning (0, "YYDEBUG was not defined at build time, -dy ignored");
#endif
- file_index = 0;
-
- do
+ i = 0;
+ for (;;)
{
- if (file_index > 0)
- {
- /* Reset the state of the parser. */
- c_reset_state();
-
- /* Reset cpplib's macros and start a new file. */
- cpp_undef_all (parse_in);
- main_input_filename = this_input_filename
- = cpp_read_main_file (parse_in, in_fnames[file_index]);
- if (this_input_filename == NULL)
- break;
- }
+ /* Start the main input file, if the debug writer wants it. */
+ if (debug_hooks->start_end_main_source_file)
+ (*debug_hooks->start_source_file) (0, this_input_filename);
finish_options ();
- if (file_index == 0)
- pch_init();
+ pch_init ();
+ push_file_scope ();
c_parse_file ();
-
- file_index++;
- } while (file_index < num_in_fnames);
-
- finish_file ();
+ finish_file ();
+ pop_file_scope ();
+ /* And end the main input file, if the debug writer wants it */
+ if (debug_hooks->start_end_main_source_file)
+ (*debug_hooks->end_source_file) (0);
+ if (++i >= num_in_fnames)
+ break;
+ cpp_undef_all (parse_in);
+ this_input_filename
+ = cpp_read_main_file (parse_in, in_fnames[i]);
+ /* If an input file is missing, abandon further compilation.
+ cpplib has issued a diagnostic. */
+ if (!this_input_filename)
+ break;
+ }
}
/* Common finish hook for the C, ObjC and C++ front ends. */
@@ -1332,6 +1272,7 @@ check_deps_environment_vars (void)
deps_file = spec;
deps_append = 1;
+ deps_seen = true;
}
}
@@ -1340,13 +1281,22 @@ static void
handle_deferred_opts (void)
{
size_t i;
+ struct deps *deps;
+
+ /* Avoid allocating the deps buffer if we don't need it.
+ (This flag may be true without there having been -MT or -MQ
+ options, but we'll still need the deps buffer.) */
+ if (!deps_seen)
+ return;
+
+ deps = cpp_get_deps (parse_in);
for (i = 0; i < deferred_count; i++)
{
struct deferred_opt *opt = &deferred_opts[i];
if (opt->code == OPT_MT || opt->code == OPT_MQ)
- cpp_add_dependency_target (parse_in, opt->arg, opt->code == OPT_MQ);
+ deps_add_target (deps, opt->arg, opt->code == OPT_MQ);
}
}
@@ -1367,7 +1317,7 @@ sanitize_cpp_opts (void)
/* Disable -dD, -dN and -dI if normal output is suppressed. Allow
-dM since at least glibc relies on -M -dM to work. */
- /* Also, flag_no_output implies flag_no_line_commands, always. */
+ /* Also, flag_no_output implies flag_no_line_commands, always. */
if (flag_no_output)
{
if (flag_dump_macros != 'M')
@@ -1384,6 +1334,11 @@ sanitize_cpp_opts (void)
cpp_opts->warn_long_long
= warn_long_long && ((!flag_isoc99 && pedantic) || warn_traditional);
+ /* Similarly with -Wno-variadic-macros. No check for c99 here, since
+ this also turns off warnings about GCCs extension. */
+ cpp_opts->warn_variadic_macros
+ = warn_variadic_macros && (pedantic || warn_traditional);
+
/* If we're generating preprocessor output, emit current directory
if explicitly requested or if debugging information is enabled.
??? Maybe we should only do it for debugging formats that
@@ -1404,12 +1359,12 @@ add_prefixed_path (const char *suffix, size_t chain)
prefix = iprefix ? iprefix : cpp_GCC_INCLUDE_DIR;
prefix_len = iprefix ? strlen (iprefix) : cpp_GCC_INCLUDE_DIR_len;
- path = xmalloc (prefix_len + suffix_len + 1);
+ path = (char *) xmalloc (prefix_len + suffix_len + 1);
memcpy (path, prefix, prefix_len);
memcpy (path + prefix_len, suffix, suffix_len);
path[prefix_len + suffix_len] = '\0';
- add_path (path, chain, 0);
+ add_path (path, chain, 0, false);
}
/* Handle -D, -U, -A, -imacros, and the first -include. */
@@ -1420,7 +1375,10 @@ finish_options (void)
{
size_t i;
- cpp_change_file (parse_in, LC_RENAME, _("<built-in>"));
+ cb_file_change (parse_in,
+ linemap_add (&line_table, LC_RENAME, 0,
+ _("<built-in>"), 0));
+
cpp_init_builtins (parse_in, flag_hosted);
c_cpp_builtins (parse_in);
@@ -1435,7 +1393,10 @@ finish_options (void)
their acceptance on the -std= setting. */
cpp_opts->warn_dollars = (cpp_opts->pedantic && !cpp_opts->c99);
- cpp_change_file (parse_in, LC_RENAME, _("<command line>"));
+ cb_file_change (parse_in,
+ linemap_add (&line_table, LC_RENAME, 0,
+ _("<command-line>"), 0));
+
for (i = 0; i < deferred_count; i++)
{
struct deferred_opt *opt = &deferred_opts[i];
@@ -1480,7 +1441,7 @@ push_command_line_include (void)
{
struct deferred_opt *opt = &deferred_opts[include_cursor++];
- if (! cpp_opts->preprocessed && opt->code == OPT_include
+ if (!cpp_opts->preprocessed && opt->code == OPT_include
&& cpp_push_include (parse_in, opt->arg))
return;
}
@@ -1491,19 +1452,18 @@ push_command_line_include (void)
/* -Wunused-macros should only warn about macros defined hereafter. */
cpp_opts->warn_unused_macros = warn_unused_macros;
/* Restore the line map from <command line>. */
- if (! cpp_opts->preprocessed)
- cpp_change_file (parse_in, LC_RENAME, main_input_filename);
+ if (!cpp_opts->preprocessed)
+ cpp_change_file (parse_in, LC_RENAME, this_input_filename);
/* Set this here so the client can change the option if it wishes,
and after stacking the main file so we don't trace the main file. */
- cpp_get_line_maps (parse_in)->trace_includes
- = cpp_opts->print_include_names;
+ line_table.trace_includes = cpp_opts->print_include_names;
}
}
/* File change callback. Has to handle -include files. */
static void
-cb_file_change (cpp_reader *pfile ATTRIBUTE_UNUSED,
+cb_file_change (cpp_reader * ARG_UNUSED (pfile),
const struct line_map *new_map)
{
if (flag_preprocess_only)
@@ -1516,10 +1476,10 @@ cb_file_change (cpp_reader *pfile ATTRIBUTE_UNUSED,
}
void
-cb_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
+cb_dir_change (cpp_reader * ARG_UNUSED (pfile), const char *dir)
{
- if (! set_src_pwd (dir))
- warning ("too late for # directive to set debug directory");
+ if (!set_src_pwd (dir))
+ warning (0, "too late for # directive to set debug directory");
}
/* Set the C 89 standard (with 1994 amendments if C94, without GNU
@@ -1534,7 +1494,6 @@ set_std_c89 (int c94, int iso)
flag_no_nonansi_builtin = iso;
flag_isoc94 = c94;
flag_isoc99 = 0;
- flag_writable_strings = 0;
}
/* Set the C 99 standard (without GNU extensions if ISO). */
@@ -1547,7 +1506,6 @@ set_std_c99 (int iso)
flag_iso = iso;
flag_isoc99 = 1;
flag_isoc94 = 1;
- flag_writable_strings = 0;
}
/* Set the C++ 98 standard (without GNU extensions if ISO). */
diff --git a/contrib/gcc/c-tree.h b/contrib/gcc/c-tree.h
index 0500f81..5139215 100644
--- a/contrib/gcc/c-tree.h
+++ b/contrib/gcc/c-tree.h
@@ -1,6 +1,6 @@
/* Definitions for C parsing and type checking.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,74 +16,28 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef GCC_C_TREE_H
#define GCC_C_TREE_H
#include "c-common.h"
+#include "toplev.h"
+#include "diagnostic.h"
-/* Language-dependent contents of an identifier. */
-
-/* The limbo_value is used for block level extern declarations, which need
- to be type checked against subsequent extern declarations. They can't
- be referenced after they fall out of scope, so they can't be global.
-
- The rid_code field is used for keywords. It is in all
- lang_identifier nodes, because some keywords are only special in a
- particular context. */
-
-struct lang_identifier GTY(())
-{
- struct c_common_identifier common_id;
- tree symbol_value;
- tree tag_value;
- tree label_value;
-};
-
-/* The resulting tree type. */
-
-union lang_tree_node
- GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
- chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *)TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
-{
- union tree_node GTY ((tag ("0"),
- desc ("tree_node_structure (&%h)")))
- generic;
- struct lang_identifier GTY ((tag ("1"))) identifier;
-};
+/* struct lang_identifier is private to c-decl.c, but langhooks.c needs to
+ know how big it is. This is sanity-checked in c-decl.c. */
+#define C_SIZEOF_STRUCT_LANG_IDENTIFIER \
+ (sizeof (struct c_common_identifier) + 3 * sizeof (void *))
/* Language-specific declaration information. */
struct lang_decl GTY(())
{
- /* The return types and parameter types may have variable size.
- This is a list of any SAVE_EXPRs that need to be evaluated to
- compute those sizes. */
- tree pending_sizes;
+ char dummy;
};
-/* Macros for access to language-specific slots in an identifier. */
-/* Each of these slots contains a DECL node or null. */
-
-/* The value of the identifier in the namespace of "ordinary identifiers"
- (data objects, enum constants, functions, typedefs). */
-#define IDENTIFIER_SYMBOL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->symbol_value)
-/* The value of the identifier in the namespace of struct, union,
- and enum tags. */
-#define IDENTIFIER_TAG_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->tag_value)
-/* The value of the identifier in the namespace of labels. */
-#define IDENTIFIER_LABEL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->label_value)
-
-/* In identifiers, C uses the following fields in a special way:
- TREE_PUBLIC to record that there was a previous local extern decl.
- TREE_USED to record that such a decl was used.
- TREE_ADDRESSABLE to record that the address of such a decl was used. */
-
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
#define C_TYPE_FIELDS_READONLY(TYPE) TREE_LANG_FLAG_1 (TYPE)
@@ -103,10 +57,17 @@ struct lang_decl GTY(())
and C_RID_YYCODE is the token number wanted by Yacc. */
#define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_0 (ID)
-/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type GTY(())
{
+ /* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
+ /* In an ENUMERAL_TYPE, the min and max values. */
+ tree enum_min;
+ tree enum_max;
+ /* In a RECORD_TYPE, information specific to Objective-C, such
+ as a list of adopted protocols or a pointer to a corresponding
+ @interface. See objc/objc-act.h for details. */
+ tree objc_info;
};
/* Record whether a type or decl was written with nonconstant size.
@@ -114,10 +75,6 @@ struct lang_type GTY(())
#define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE)
#define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE)
-/* Store a value in that field. */
-#define C_SET_EXP_ORIGINAL_CODE(EXP, CODE) \
- (TREE_COMPLEXITY (EXP) = (int) (CODE))
-
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
@@ -128,11 +85,53 @@ struct lang_type GTY(())
/* For a FUNCTION_DECL, nonzero if it was an implicit declaration. */
#define C_DECL_IMPLICIT(EXP) DECL_LANG_FLAG_2 (EXP)
-/* Nonzero for a declaration of an external object which is not
- currently in scope. This is either a built-in declaration of
- a library function, before a real declaration has been seen,
- or a declaration that appeared in an inner scope that has ended. */
-#define C_DECL_INVISIBLE(EXP) DECL_LANG_FLAG_3 (EXP)
+/* For FUNCTION_DECLs, evaluates true if the decl is built-in but has
+ been declared. */
+#define C_DECL_DECLARED_BUILTIN(EXP) \
+ DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (EXP))
+
+/* For FUNCTION_DECLs, evaluates true if the decl is built-in, has a
+ built-in prototype and does not have a non-built-in prototype. */
+#define C_DECL_BUILTIN_PROTOTYPE(EXP) \
+ DECL_LANG_FLAG_6 (FUNCTION_DECL_CHECK (EXP))
+
+/* Record whether a decl was declared register. This is strictly a
+ front-end flag, whereas DECL_REGISTER is used for code generation;
+ they may differ for structures with volatile fields. */
+#define C_DECL_REGISTER(EXP) DECL_LANG_FLAG_4 (EXP)
+
+/* Record whether a decl was used in an expression anywhere except an
+ unevaluated operand of sizeof / typeof / alignof. This is only
+ used for functions declared static but not defined, though outside
+ sizeof and typeof it is set for other function decls as well. */
+#define C_DECL_USED(EXP) DECL_LANG_FLAG_5 (FUNCTION_DECL_CHECK (EXP))
+
+/* Record whether a label was defined in a statement expression which
+ has finished and so can no longer be jumped to. */
+#define C_DECL_UNJUMPABLE_STMT_EXPR(EXP) \
+ DECL_LANG_FLAG_6 (LABEL_DECL_CHECK (EXP))
+
+/* Record whether a label was the subject of a goto from outside the
+ current level of statement expression nesting and so cannot be
+ defined right now. */
+#define C_DECL_UNDEFINABLE_STMT_EXPR(EXP) \
+ DECL_LANG_FLAG_7 (LABEL_DECL_CHECK (EXP))
+
+/* Record whether a label was defined in the scope of an identifier
+ with variably modified type which has finished and so can no longer
+ be jumped to. */
+#define C_DECL_UNJUMPABLE_VM(EXP) \
+ DECL_LANG_FLAG_3 (LABEL_DECL_CHECK (EXP))
+
+/* Record whether a label was the subject of a goto from outside the
+ current level of scopes of identifiers with variably modified type
+ and so cannot be defined right now. */
+#define C_DECL_UNDEFINABLE_VM(EXP) \
+ DECL_LANG_FLAG_5 (LABEL_DECL_CHECK (EXP))
+
+/* Record whether a variable has been declared threadprivate by
+ #pragma omp threadprivate. */
+#define C_DECL_THREADPRIVATE_P(DECL) DECL_LANG_FLAG_3 (VAR_DECL_CHECK (DECL))
/* Nonzero for a decl which either doesn't exist or isn't a prototype.
N.B. Could be simplified if all built-in decls had complete prototypes
@@ -145,12 +144,230 @@ struct lang_type GTY(())
/* For FUNCTION_TYPE, a hidden list of types of arguments. The same as
TYPE_ARG_TYPES for functions with prototypes, but created for functions
without prototypes. */
-#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_BINFO (NODE)
+#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_LANG_SLOT_1 (NODE)
-/* Values for the first parameter to poplevel. */
-#define KEEP_NO 0
-#define KEEP_YES 1
-#define KEEP_MAYBE 2
+/* Record parser information about an expression that is irrelevant
+ for code generation alongside a tree representing its value. */
+struct c_expr
+{
+ /* The value of the expression. */
+ tree value;
+ /* Record the original binary operator of an expression, which may
+ have been changed by fold, STRING_CST for unparenthesized string
+ constants, or ERROR_MARK for other expressions (including
+ parenthesized expressions). */
+ enum tree_code original_code;
+};
+
+/* A kind of type specifier. Note that this information is currently
+ only used to distinguish tag definitions, tag references and typeof
+ uses. */
+enum c_typespec_kind {
+ /* A reserved keyword type specifier. */
+ ctsk_resword,
+ /* A reference to a tag, previously declared, such as "struct foo".
+ This includes where the previous declaration was as a different
+ kind of tag, in which case this is only valid if shadowing that
+ tag in an inner scope. */
+ ctsk_tagref,
+ /* A reference to a tag, not previously declared in a visible
+ scope. */
+ ctsk_tagfirstref,
+ /* A definition of a tag such as "struct foo { int a; }". */
+ ctsk_tagdef,
+ /* A typedef name. */
+ ctsk_typedef,
+ /* An ObjC-specific kind of type specifier. */
+ ctsk_objc,
+ /* A typeof specifier. */
+ ctsk_typeof
+};
+
+/* A type specifier: this structure is created in the parser and
+ passed to declspecs_add_type only. */
+struct c_typespec {
+ /* What kind of type specifier this is. */
+ enum c_typespec_kind kind;
+ /* The specifier itself. */
+ tree spec;
+};
+
+/* A storage class specifier. */
+enum c_storage_class {
+ csc_none,
+ csc_auto,
+ csc_extern,
+ csc_register,
+ csc_static,
+ csc_typedef
+};
+
+/* A type specifier keyword "void", "_Bool", "char", "int", "float",
+ "double", or none of these. */
+enum c_typespec_keyword {
+ cts_none,
+ cts_void,
+ cts_bool,
+ cts_char,
+ cts_int,
+ cts_float,
+ cts_double,
+ cts_dfloat32,
+ cts_dfloat64,
+ cts_dfloat128
+};
+
+/* A sequence of declaration specifiers in C. */
+struct c_declspecs {
+ /* The type specified, if a single type specifier such as a struct,
+ union or enum specifier, typedef name or typeof specifies the
+ whole type, or NULL_TREE if none or a keyword such as "void" or
+ "char" is used. Does not include qualifiers. */
+ tree type;
+ /* The attributes from a typedef decl. */
+ tree decl_attr;
+ /* When parsing, the attributes. Outside the parser, this will be
+ NULL; attributes (possibly from multiple lists) will be passed
+ separately. */
+ tree attrs;
+ /* Any type specifier keyword used such as "int", not reflecting
+ modifiers such as "short", or cts_none if none. */
+ enum c_typespec_keyword typespec_word;
+ /* The storage class specifier, or csc_none if none. */
+ enum c_storage_class storage_class;
+ /* Whether any declaration specifiers have been seen at all. */
+ BOOL_BITFIELD declspecs_seen_p : 1;
+ /* Whether a type specifier has been seen. */
+ BOOL_BITFIELD type_seen_p : 1;
+ /* Whether something other than a storage class specifier or
+ attribute has been seen. This is used to warn for the
+ obsolescent usage of storage class specifiers other than at the
+ start of the list. (Doing this properly would require function
+ specifiers to be handled separately from storage class
+ specifiers.) */
+ BOOL_BITFIELD non_sc_seen_p : 1;
+ /* Whether the type is specified by a typedef or typeof name. */
+ BOOL_BITFIELD typedef_p : 1;
+ /* Whether a struct, union or enum type either had its content
+ defined by a type specifier in the list or was the first visible
+ declaration of its tag. */
+ BOOL_BITFIELD tag_defined_p : 1;
+ /* Whether the type is explicitly "signed" or specified by a typedef
+ whose type is explicitly "signed". */
+ BOOL_BITFIELD explicit_signed_p : 1;
+ /* Whether the specifiers include a deprecated typedef. */
+ BOOL_BITFIELD deprecated_p : 1;
+ /* Whether the type defaulted to "int" because there were no type
+ specifiers. */
+ BOOL_BITFIELD default_int_p;
+ /* Whether "long" was specified. */
+ BOOL_BITFIELD long_p : 1;
+ /* Whether "long" was specified more than once. */
+ BOOL_BITFIELD long_long_p : 1;
+ /* Whether "short" was specified. */
+ BOOL_BITFIELD short_p : 1;
+ /* Whether "signed" was specified. */
+ BOOL_BITFIELD signed_p : 1;
+ /* Whether "unsigned" was specified. */
+ BOOL_BITFIELD unsigned_p : 1;
+ /* Whether "complex" was specified. */
+ BOOL_BITFIELD complex_p : 1;
+ /* Whether "inline" was specified. */
+ BOOL_BITFIELD inline_p : 1;
+ /* Whether "__thread" was specified. */
+ BOOL_BITFIELD thread_p : 1;
+ /* Whether "const" was specified. */
+ BOOL_BITFIELD const_p : 1;
+ /* Whether "volatile" was specified. */
+ BOOL_BITFIELD volatile_p : 1;
+ /* Whether "restrict" was specified. */
+ BOOL_BITFIELD restrict_p : 1;
+};
+
+/* The various kinds of declarators in C. */
+enum c_declarator_kind {
+ /* An identifier. */
+ cdk_id,
+ /* A function. */
+ cdk_function,
+ /* An array. */
+ cdk_array,
+ /* A pointer. */
+ cdk_pointer,
+ /* Parenthesized declarator with nested attributes. */
+ cdk_attrs
+};
+
+/* Information about the parameters in a function declarator. */
+struct c_arg_info {
+ /* A list of parameter decls. */
+ tree parms;
+ /* A list of structure, union and enum tags defined. */
+ tree tags;
+ /* A list of argument types to go in the FUNCTION_TYPE. */
+ tree types;
+ /* A list of non-parameter decls (notably enumeration constants)
+ defined with the parameters. */
+ tree others;
+ /* A list of VLA sizes from the parameters. In a function
+ definition, these are used to ensure that side-effects in sizes
+ of arrays converted to pointers (such as a parameter int i[n++])
+ take place; otherwise, they are ignored. */
+ tree pending_sizes;
+ /* True when these arguments had [*]. */
+ BOOL_BITFIELD had_vla_unspec : 1;
+};
+
+/* A declarator. */
+struct c_declarator {
+ /* The kind of declarator. */
+ enum c_declarator_kind kind;
+ /* Except for cdk_id, the contained declarator. For cdk_id, NULL. */
+ struct c_declarator *declarator;
+ location_t id_loc; /* Currently only set for cdk_id. */
+ union {
+ /* For identifiers, an IDENTIFIER_NODE or NULL_TREE if an abstract
+ declarator. */
+ tree id;
+ /* For functions. */
+ struct c_arg_info *arg_info;
+ /* For arrays. */
+ struct {
+ /* The array dimension, or NULL for [] and [*]. */
+ tree dimen;
+ /* The qualifiers inside []. */
+ int quals;
+ /* The attributes (currently ignored) inside []. */
+ tree attrs;
+ /* Whether [static] was used. */
+ BOOL_BITFIELD static_p : 1;
+ /* Whether [*] was used. */
+ BOOL_BITFIELD vla_unspec_p : 1;
+ } array;
+ /* For pointers, the qualifiers on the pointer type. */
+ int pointer_quals;
+ /* For attributes. */
+ tree attrs;
+ } u;
+};
+
+/* A type name. */
+struct c_type_name {
+ /* The declaration specifiers. */
+ struct c_declspecs *specs;
+ /* The declarator. */
+ struct c_declarator *declarator;
+};
+
+/* A parameter. */
+struct c_parm {
+ /* The declaration specifiers, minus any prefix attributes. */
+ struct c_declspecs *specs;
+ /* The attributes. */
+ tree attrs;
+ /* The declarator. */
+ struct c_declarator *declarator;
+};
/* Save and restore the variables in this file and elsewhere
that keep track of the progress of compilation of the current function.
@@ -159,140 +376,219 @@ struct lang_type GTY(())
struct language_function GTY(())
{
struct c_language_function base;
+ tree x_break_label;
+ tree x_cont_label;
+ struct c_switch * GTY((skip)) x_switch_stack;
+ struct c_arg_info * GTY((skip)) arg_info;
int returns_value;
int returns_null;
int returns_abnormally;
int warn_about_return_type;
int extern_inline;
- int x_in_iteration_stmt;
- int x_in_case_stmt;
+};
+
+/* Save lists of labels used or defined in particular contexts.
+ Allocated on the parser obstack. */
+
+struct c_label_list
+{
+ /* The label at the head of the list. */
+ tree label;
+ /* The rest of the list. */
+ struct c_label_list *next;
+};
+
+/* Statement expression context. */
+
+struct c_label_context_se
+{
+ /* The labels defined at this level of nesting. */
+ struct c_label_list *labels_def;
+ /* The labels used at this level of nesting. */
+ struct c_label_list *labels_used;
+ /* The next outermost context. */
+ struct c_label_context_se *next;
+};
+
+/* Context of variably modified declarations. */
+
+struct c_label_context_vm
+{
+ /* The labels defined at this level of nesting. */
+ struct c_label_list *labels_def;
+ /* The labels used at this level of nesting. */
+ struct c_label_list *labels_used;
+ /* The scope of this context. Multiple contexts may be at the same
+ numbered scope, since each variably modified declaration starts a
+ new context. */
+ unsigned scope;
+ /* The next outermost context. */
+ struct c_label_context_vm *next;
};
-/* in c-parse.in */
+/* in c-parser.c */
extern void c_parse_init (void);
/* in c-aux-info.c */
extern void gen_aux_info_record (tree, int, int, int);
/* in c-decl.c */
-extern int c_in_iteration_stmt;
-extern int c_in_case_stmt;
+extern struct obstack parser_obstack;
+extern tree c_break_label;
+extern tree c_cont_label;
extern int global_bindings_p (void);
-extern tree getdecls (void);
-extern void pushlevel (int);
+extern void push_scope (void);
+extern tree pop_scope (void);
extern void insert_block (tree);
-extern void set_block (tree);
-extern tree pushdecl (tree);
extern void c_expand_body (tree);
extern void c_init_decl_processing (void);
extern void c_dup_lang_specific_decl (tree);
extern void c_print_identifier (FILE *, tree, int);
-extern tree build_array_declarator (tree, tree, int, int);
+extern int quals_from_declspecs (const struct c_declspecs *);
+extern struct c_declarator *build_array_declarator (tree, struct c_declspecs *,
+ bool, bool);
extern tree build_enumerator (tree, tree);
-extern void check_for_loop_decls (void);
+extern tree check_for_loop_decls (void);
extern void mark_forward_parm_decls (void);
-extern int complete_array_type (tree, tree, int);
extern void declare_parm_level (void);
-extern void undeclared_variable (tree);
+extern void undeclared_variable (tree, location_t);
extern tree declare_label (tree);
extern tree define_label (location_t, tree);
+extern void c_maybe_initialize_eh (void);
extern void finish_decl (tree, tree, tree);
extern tree finish_enum (tree, tree, tree);
extern void finish_function (void);
extern tree finish_struct (tree, tree, tree);
-extern tree get_parm_info (int);
-extern tree grokfield (tree, tree, tree);
-extern tree groktypename (tree);
-extern tree groktypename_in_parm_context (tree);
+extern struct c_arg_info *get_parm_info (bool);
+extern tree grokfield (struct c_declarator *, struct c_declspecs *, tree);
+extern tree groktypename (struct c_type_name *);
+extern tree grokparm (const struct c_parm *);
extern tree implicitly_declare (tree);
-extern int in_parm_level_p (void);
extern void keep_next_level (void);
-extern tree lookup_name (tree);
extern void pending_xref_error (void);
extern void c_push_function_context (struct function *);
extern void c_pop_function_context (struct function *);
-extern void push_parm_decl (tree);
-extern tree pushdecl_top_level (tree);
-extern void pushtag (tree, tree);
-extern tree set_array_declarator_type (tree, tree, int);
-extern void shadow_tag (tree);
-extern void shadow_tag_warned (tree, int);
+extern void push_parm_decl (const struct c_parm *);
+extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
+ struct c_declarator *,
+ bool);
+extern tree builtin_function (const char *, tree, int, enum built_in_class,
+ const char *, tree);
+extern void shadow_tag (const struct c_declspecs *);
+extern void shadow_tag_warned (const struct c_declspecs *, int);
extern tree start_enum (tree);
-extern int start_function (tree, tree, tree);
-extern tree start_decl (tree, tree, int, tree);
+extern int start_function (struct c_declspecs *, struct c_declarator *, tree);
+extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
+ tree);
extern tree start_struct (enum tree_code, tree);
extern void store_parm_decls (void);
+extern void store_parm_decls_from (struct c_arg_info *);
extern tree xref_tag (enum tree_code, tree);
-extern tree c_begin_compound_stmt (void);
-extern void c_expand_deferred_function (tree);
-extern void c_expand_decl_stmt (tree);
-extern void c_static_assembler_name (tree);
-extern tree make_pointer_declarator (tree, tree);
-extern void merge_translation_unit_decls (void);
+extern struct c_typespec parser_xref_tag (enum tree_code, tree);
+extern int c_expand_decl (tree);
+extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
+ struct c_declarator *);
+extern struct c_declarator *build_attrs_declarator (tree,
+ struct c_declarator *);
+extern struct c_declarator *build_function_declarator (struct c_arg_info *,
+ struct c_declarator *);
+extern struct c_declarator *build_id_declarator (tree);
+extern struct c_declarator *make_pointer_declarator (struct c_declspecs *,
+ struct c_declarator *);
+extern struct c_declspecs *build_null_declspecs (void);
+extern struct c_declspecs *declspecs_add_qual (struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_type (struct c_declspecs *,
+ struct c_typespec);
+extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree);
+extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
/* in c-objc-common.c */
extern int c_disregard_inline_limits (tree);
extern int c_cannot_inline_tree_fn (tree *);
extern bool c_objc_common_init (void);
-extern int c_missing_noreturn_ok_p (tree);
-extern void c_objc_common_finish_file (void);
-extern int defer_fn (tree);
+extern bool c_missing_noreturn_ok_p (tree);
+extern tree c_objc_common_truthvalue_conversion (tree expr);
extern bool c_warn_unused_global_decl (tree);
+extern void c_initialize_diagnostics (diagnostic_context *);
+extern bool c_vla_unspec_p (tree x, tree fn);
#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
c_build_qualified_type ((TYPE), \
((CONST_P) ? TYPE_QUAL_CONST : 0) | \
((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
-#define c_sizeof_nowarn(T) c_sizeof_or_alignof_type (T, SIZEOF_EXPR, 0)
-
/* in c-typeck.c */
+extern int in_alignof;
+extern int in_sizeof;
+extern int in_typeof;
-/* For use with comptypes. */
-enum {
- COMPARE_STRICT = 0
-};
+extern struct c_switch *c_switch_stack;
+extern struct c_label_context_se *label_context_stack_se;
+extern struct c_label_context_vm *label_context_stack_vm;
extern tree require_complete_type (tree);
-extern int comptypes (tree, tree, int);
-extern tree c_size_in_bytes (tree);
+extern int same_translation_unit_p (tree, tree);
+extern int comptypes (tree, tree);
+extern bool c_vla_type_p (tree);
extern bool c_mark_addressable (tree);
extern void c_incomplete_type_error (tree, tree);
extern tree c_type_promotes_to (tree);
+extern struct c_expr default_function_array_conversion (struct c_expr);
+extern tree composite_type (tree, tree);
extern tree build_component_ref (tree, tree);
-extern tree build_indirect_ref (tree, const char *);
extern tree build_array_ref (tree, tree);
-extern tree build_external_ref (tree, int);
-extern tree parser_build_binary_op (enum tree_code, tree, tree);
-extern int c_tree_expr_nonnegative_p (tree);
-extern void readonly_error (tree, const char *);
+extern tree build_external_ref (tree, int, location_t);
+extern void pop_maybe_used (bool);
+extern struct c_expr c_expr_sizeof_expr (struct c_expr);
+extern struct c_expr c_expr_sizeof_type (struct c_type_name *);
+extern struct c_expr parser_build_unary_op (enum tree_code, struct c_expr);
+extern struct c_expr parser_build_binary_op (enum tree_code, struct c_expr,
+ struct c_expr);
extern tree build_conditional_expr (tree, tree, tree);
-extern tree build_compound_expr (tree);
-extern tree c_cast_expr (tree, tree);
+extern tree build_compound_expr (tree, tree);
+extern tree c_cast_expr (struct c_type_name *, tree);
extern tree build_c_cast (tree, tree);
-extern tree build_modify_expr (tree, enum tree_code, tree);
extern void store_init_value (tree, tree);
extern void error_init (const char *);
extern void pedwarn_init (const char *);
+extern void maybe_warn_string_init (tree, struct c_expr);
extern void start_init (tree, tree, int);
extern void finish_init (void);
extern void really_start_incremental_init (tree);
extern void push_init_level (int);
-extern tree pop_init_level (int);
+extern struct c_expr pop_init_level (int);
extern void set_init_index (tree, tree);
extern void set_init_label (tree);
-extern void process_init_element (tree);
+extern void process_init_element (struct c_expr);
extern tree build_compound_literal (tree, tree);
-extern void pedwarn_c90 (const char *, ...) ATTRIBUTE_PRINTF_1;
-extern void pedwarn_c99 (const char *, ...) ATTRIBUTE_PRINTF_1;
extern tree c_start_case (tree);
-extern void c_finish_case (void);
-extern tree simple_asm_stmt (tree);
-extern tree build_asm_stmt (tree, tree, tree, tree, tree);
+extern void c_finish_case (tree);
+extern tree build_asm_expr (tree, tree, tree, tree, bool);
+extern tree build_asm_stmt (tree, tree);
extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
+extern int c_types_compatible_p (tree, tree);
+extern tree c_begin_compound_stmt (bool);
+extern tree c_end_compound_stmt (tree, bool);
+extern void c_finish_if_stmt (location_t, tree, tree, tree, bool);
+extern void c_finish_loop (location_t, tree, tree, tree, tree, tree, bool);
+extern tree c_begin_stmt_expr (void);
+extern tree c_finish_stmt_expr (tree);
+extern tree c_process_expr_stmt (tree);
+extern tree c_finish_expr_stmt (tree);
+extern tree c_finish_return (tree);
+extern tree c_finish_bc_stmt (tree *, bool);
+extern tree c_finish_goto_label (tree);
+extern tree c_finish_goto_ptr (tree);
+extern void c_begin_vm_scope (unsigned int);
+extern void c_end_vm_scope (unsigned int);
+extern tree c_expr_to_decl (tree, bool *, bool *, bool *);
+extern tree c_begin_omp_parallel (void);
+extern tree c_finish_omp_parallel (tree, tree);
+extern tree c_finish_omp_clauses (tree);
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -313,18 +609,28 @@ extern int current_function_returns_abnormally;
extern int system_header_p;
+/* True means global_bindings_p should return false even if the scope stack
+ says we are in file scope. */
+
+extern bool c_override_global_bindings_to_false;
+
+/* True means we've initialized exception handling. */
+extern bool c_eh_initialized_p;
+
/* In c-decl.c */
extern void c_finish_incomplete_decl (tree);
-extern void *get_current_scope (void);
-extern void objc_mark_locals_volatile (void *);
extern void c_write_global_declarations (void);
-extern GTY(()) tree static_ctors;
-extern GTY(()) tree static_dtors;
-
/* In order for the format checking to accept the C frontend
diagnostic framework extensions, you must include this file before
toplev.h, not after. */
-#define GCC_DIAG_STYLE __gcc_cdiag__
+#if GCC_VERSION >= 4001
+#define ATTRIBUTE_GCC_CDIAG(m, n) __attribute__ ((__format__ (GCC_DIAG_STYLE, m ,n))) ATTRIBUTE_NONNULL(m)
+#else
+#define ATTRIBUTE_GCC_CDIAG(m, n) ATTRIBUTE_NONNULL(m)
+#endif
+
+extern void pedwarn_c90 (const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2);
+extern void pedwarn_c99 (const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2);
#endif /* ! GCC_C_TREE_H */
diff --git a/contrib/gcc/c.opt b/contrib/gcc/c.opt
index 0568463..8769657 100644
--- a/contrib/gcc/c.opt
+++ b/contrib/gcc/c.opt
@@ -1,5 +1,5 @@
; Options for the C, ObjC, C++ and ObjC++ front ends.
-; Copyright (C) 2003 Free Software Foundation, Inc.
+; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
;
; This file is part of GCC.
;
@@ -7,59 +7,21 @@
; the terms of the GNU General Public License as published by the Free
; Software Foundation; either version 2, or (at your option) any later
; version.
-;
+;
; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
; WARRANTY; without even the implied warranty of MERCHANTABILITY or
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
; for more details.
-;
+;
; You should have received a copy of the GNU General Public License
; along with GCC; see the file COPYING. If not, write to the Free
-; Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-; 02111-1307, USA.
-
-
-; This file is processed by the script opts.sh. It is a database of
-; command line options, with each record separated by a blank line,
-; and each field appearing on its own line. The first field is the
-; command-line switch with the leading "-" removed. All options
-; beginning with "f" or "W" are implicitly assumed to take a "no-"
-; form; this form should not be listed. If you do not want this
-; negative form and you want it to be automatically rejected, add
-; RejectNegative to the second field.
-
-; The second field is a space-separated list of which parts of the
-; compiler recognize the switch, as declared by "Language" entries.
-; If the switch takes an argument, then you should also specify
-; "Joined" and/or "Separate" to indicate where the argument can
-; appear. If a Joined argument can legitimately be omitted, specify
-; "JoinedOrMissing" instead of "Joined". If the argument to a switch
-; is a non-negative integer, you can specify "UInteger" and the switch
-; decoder will convert the argument for you, or complain to the user
-; if the argument is invalid.
-
-; The third field is the help text to output with --help. This is
-; automatically line-wrapped on output. Normally the switch is output
-; automatically, with the help text on the right hand side of the
-; output. However, if the help text contains a tab character, the
-; text to the left of the tab is output instead of the switch, and the
-; text to its right forms the help. This is useful for elaborating on
-; what type of argument a switch takes, for example. If the second
-; field contains "Undocumented" then nothing is output with --help.
-; Only do this with good reason like the switch being internal between
-; the driver and the front end - it is not an excuse to leave a switch
-; undocumented.
-
-; Comments can appear on their own line anwhere in the file, preceded
-; by a semicolon. Whitespace is permitted before the semicolon.
-
-; For each switch XXX below, an enumeration constant is created by the
-; script opts.sh spelt OPT_XXX, but with all non-alphanumeric
-; characters replaced with an underscore.
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
-; Please try to keep this file in ASCII collating order.
+; See the GCC internals manual for a description of this file's format.
; $FreeBSD$
+; Please try to keep this file in ASCII collating order.
Language
C
@@ -95,13 +57,17 @@ C ObjC C++ ObjC++ Joined Separate
E
C ObjC C++ ObjC++ Undocumented
+F
+C ObjC C++ ObjC++ Joined Separate
+-F <dir> Add <dir> to the end of the main framework include path
+
H
C ObjC C++ ObjC++
Print the name of header files as they are used
I
C ObjC C++ ObjC++ Joined Separate
--I <dir> Add <dir> to the end of the main include path. -I- gives more include path control; see info documentation
+-I <dir> Add <dir> to the end of the main include path
M
C ObjC C++ ObjC++
@@ -148,22 +114,36 @@ C ObjC C++ ObjC++ Joined Separate
-U<macro> Undefine <macro>
Wabi
-C++ ObjC++
+C++ ObjC++ Var(warn_abi)
+Warn about things that will change when compiling with an ABI-compliant compiler
+
+Waddress
+C ObjC C++ ObjC++ Var(warn_address)
+Warn about suspicious uses of memory addresses
Wall
C ObjC C++ ObjC++
Enable most warning messages
+Wassign-intercept
+ObjC ObjC++ Var(warn_assign_intercept)
+Warn whenever an Objective-C assignment is being intercepted by the garbage collector
+
Wbad-function-cast
-C ObjC
+C ObjC Var(warn_bad_function_cast)
Warn about casting functions to incompatible types
+Wc++-compat
+C ObjC Var(warn_cxx_compat)
+Warn about C constructs that are not in the common subset of C and C++
+
+
Wcast-qual
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_cast_qual)
Warn about casts which discard qualifiers
Wchar-subscripts
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_char_subscripts)
Warn about subscripts whose type is \"char\"
Wcomment
@@ -175,27 +155,27 @@ C ObjC C++ ObjC++
Synonym for -Wcomment
Wconversion
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_conversion)
Warn about possibly confusing type conversions
Wctor-dtor-privacy
-C++ ObjC++
+C++ ObjC++ Var(warn_ctor_dtor_privacy)
Warn when all constructors and destructors are private
Wdeclaration-after-statement
-C ObjC
+C ObjC Var(warn_declaration_after_statement)
Warn when a declaration is found after a statement
Wdeprecated
-C++ ObjC++
+C++ ObjC++ Var(warn_deprecated) Init(1)
Warn about deprecated compiler features
Wdiv-by-zero
-C ObjC
+C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1)
Warn about compile-time integer division by zero
Weffc++
-C++ ObjC++
+C++ ObjC++ Var(warn_ecpp)
Warn about violations of Effective C++ style rules
Wendif-labels
@@ -211,7 +191,7 @@ C ObjC RejectNegative
Make implicit function declarations an error
Wfloat-equal
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_float_equal)
Warn if testing floating point numbers for equality
Wformat
@@ -219,48 +199,53 @@ C ObjC C++ ObjC++
Warn about printf/scanf/strftime/strfmon format string anomalies
Wformat-extra-args
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_format_extra_args)
Warn if passing too many arguments to a function for its format string
Wformat-nonliteral
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_format_nonliteral)
Warn about format strings that are not literals
Wformat-security
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_format_security)
Warn about possible security problems with format functions
Wformat-y2k
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_format_y2k)
Warn about strftime formats yielding 2-digit years
Wformat-zero-length
-C ObjC
+C ObjC Var(warn_format_zero_length)
+Warn about zero-length formats
Wformat=
C ObjC C++ ObjC++ Joined
Winit-self
-C ObjC C++ ObjC++
-Warn about variables which are initialized to themselves.
+C ObjC C++ ObjC++ Var(warn_init_self)
+Warn about variables which are initialized to themselves
Wimplicit
C ObjC C++ ObjC++
Wimplicit-function-declaration
-C ObjC
+C ObjC Var(mesg_implicit_function_declaration) Init(-1)
Warn about implicit function declarations
Wimplicit-int
-C ObjC
+C ObjC Var(warn_implicit_int)
Warn when a declaration does not specify a type
Wimport
C ObjC C++ ObjC++
-Deprecated. This switch has no effect.
+Deprecated. This switch has no effect
+
+Wint-to-pointer-cast
+C ObjC Var(warn_int_to_pointer_cast) Init(1)
+Warn when there is a cast to a pointer from an integer of a different size
Winvalid-offsetof
-C++ ObjC++
+C++ ObjC++ Var(warn_invalid_offsetof) Init(1)
Warn about invalid uses of the \"offsetof\" macro
Winvalid-pch
@@ -268,7 +253,7 @@ C ObjC C++ ObjC++
Warn about PCH files that are found but not used
Wlong-long
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_long_long) Init(1)
Do not warn about using \"long long\" when -pedantic
Wmain
@@ -276,19 +261,27 @@ C ObjC
Warn about suspicious declarations of \"main\"
Wmissing-braces
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_missing_braces)
Warn about possibly missing braces around initializers
Wmissing-declarations
-C ObjC
+C ObjC Var(warn_missing_declarations)
Warn about global functions without previous declarations
+Wmissing-field-initializers
+C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Init(-1)
+Warn about missing fields in struct initializers
+
Wmissing-format-attribute
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_missing_format_attribute)
Warn about functions which might be candidates for format attributes
+Wmissing-include-dirs
+C ObjC C++ ObjC++
+Warn about user-specified include directories that do not exist
+
Wmissing-prototypes
-C ObjC
+C ObjC Var(warn_missing_prototypes)
Warn about global functions without prototypes
Wmultichar
@@ -296,82 +289,111 @@ C ObjC C++ ObjC++
Warn about use of multi-character character constants
Wnested-externs
-C ObjC
+C ObjC Var(warn_nested_externs)
Warn about \"extern\" declarations not at file scope
Wnon-template-friend
-C++ ObjC++
+C++ ObjC++ Var(warn_nontemplate_friend) Init(1)
Warn when non-templatized friend functions are declared within a template
Wnon-virtual-dtor
-C++ ObjC++
+C++ ObjC++ Var(warn_nonvdtor)
Warn about non-virtual destructors
Wnonnull
-C ObjC
+C ObjC Var(warn_nonnull)
+Warn about NULL being passed to argument slots marked as requiring non-NULL
+
+Wnormalized=
+C ObjC C++ ObjC++ Joined
+-Wnormalized=<id|nfc|nfkc> Warn about non-normalised Unicode strings
Wold-style-cast
-C++ ObjC++
+C++ ObjC++ Var(warn_old_style_cast)
Warn if a C-style cast is used in a program
Wold-style-definition
-C ObjC
+C ObjC Var(warn_old_style_definition)
Warn if an old-style parameter definition is used
+Woverlength-strings
+C ObjC C++ ObjC++ Var(warn_overlength_strings) Init(-1)
+Warn if a string is longer than the maximum portable length specified by the standard
+
Woverloaded-virtual
-C++ ObjC++
+C++ ObjC++ Var(warn_overloaded_virtual)
Warn about overloaded virtual function names
+Woverride-init
+C ObjC Var(warn_override_init) Init(-1)
+Warn about overriding initializers without side effects
+
Wparentheses
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_parentheses)
Warn about possibly missing parentheses
Wpmf-conversions
-C++ ObjC++
+C++ ObjC++ Var(warn_pmf2ptr) Init(1)
Warn when converting the type of pointers to member functions
Wpointer-arith
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_pointer_arith)
Warn about function pointer arithmetic
+Wpointer-to-int-cast
+C ObjC Var(warn_pointer_to_int_cast) Init(1)
+Warn when a pointer is cast to an integer of a different size
+
+Wpragmas
+C ObjC C++ ObjC++ Var(warn_pragmas) Init(1)
+Warn about misuses of pragmas
+
Wprotocol
-ObjC ObjC++
+ObjC ObjC++ Var(warn_protocol) Init(1)
Warn if inherited methods are unimplemented
Wredundant-decls
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_redundant_decls)
Warn about multiple declarations of the same object
Wreorder
-C++ ObjC++
+C++ ObjC++ Var(warn_reorder)
Warn when the compiler reorders code
Wreturn-type
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_return_type)
Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++)
Wselector
-ObjC ObjC++
+ObjC ObjC++ Var(warn_selector)
Warn if a selector has multiple methods
Wsequence-point
-C ObjC
+C ObjC C++ ObjC++ Var(warn_sequence_point)
Warn about possible violations of sequence point rules
Wsign-compare
-C ObjC C++ ObjC++
+C ObjC C++ ObjC++ Var(warn_sign_compare) Init(-1)
Warn about signed-unsigned comparisons
Wsign-promo
-C++ ObjC++
+C++ ObjC++ Var(warn_sign_promo)
Warn when overload promotes from unsigned to signed
+Wstrict-null-sentinel
+C++ ObjC++
+Warn about uncasted NULL used as sentinel
+
Wstrict-prototypes
-C ObjC
+C ObjC Var(warn_strict_prototypes)
Warn about unprototyped function declarations
+Wstrict-selector-match
+ObjC ObjC++ Var(warn_strict_selector_match)
+Warn if type signatures of candidate methods do not match exactly
+
Wsynth
-C++ ObjC++
+C++ ObjC++ Var(warn_synth)
Warn when synthesis behavior differs from Cfront
Wsystem-headers
@@ -379,7 +401,7 @@ C ObjC C++ ObjC++
Do not suppress warnings from system headers
Wtraditional
-C ObjC
+C ObjC Var(warn_traditional)
Warn about features not present in traditional C
Wtrigraphs
@@ -387,7 +409,8 @@ C ObjC C++ ObjC++
Warn if trigraphs are encountered that might affect the meaning of the program
Wundeclared-selector
-ObjC ObjC++
+ObjC ObjC++ Var(warn_undeclared_selector)
+Warn about @selector()s without previously declared methods
Wundef
C ObjC C++ ObjC++
@@ -401,13 +424,21 @@ Wunused-macros
C ObjC C++ ObjC++
Warn about macros defined in the main file that are not used
-Wwrite-strings
+Wvariadic-macros
C ObjC C++ ObjC++
-Give strings the type \"array of char\"
+Do not warn about using variadic macros when -pedantic
+
+Wwrite-strings
+C ObjC C++ ObjC++ Var(warn_write_strings)
+In C++, nonzero means warn about deprecated conversion from string literals to `char *'. In C, similar warning, except that the conversion is of course not deprecated by the ISO C standard.
+
+Wpointer-sign
+C ObjC Var(warn_pointer_sign) Init(-1)
+Warn when a pointer differs in signedness in an assignment
ansi
C ObjC C++ ObjC++
-A synonym for -std=c89 (for C) or -std=c++98 (for C++).
+A synonym for -std=c89 (for C) or -std=c++98 (for C++)
d
C ObjC C++ ObjC++ Joined
@@ -447,10 +478,6 @@ fconserve-space
C++ ObjC++
Reduce the size of object files
-fconst-strings
-C++ ObjC++
-Make string literals \"const char[]\" not \"char[]\"
-
fconstant-string-class=
ObjC ObjC++ Joined
-fconst-string-class=<name> Use class <name> for constant strings
@@ -463,10 +490,6 @@ fdollars-in-identifiers
C ObjC C++ ObjC++
Permit '$' as an identifier character
-fdump-
-C ObjC C++ ObjC++ Joined RejectNegative
--fdump-<type> Dump various compiler internals to a file
-
felide-constructors
C++ ObjC++
@@ -481,20 +504,18 @@ fexec-charset=
C ObjC C++ ObjC++ Joined RejectNegative
-fexec-charset=<cset> Convert all strings and character constants to character set <cset>
+fextended-identifiers
+C ObjC C++ ObjC++
+Permit universal character names (\\u and \\U) in identifiers
+
finput-charset=
C ObjC C++ ObjC++ Joined RejectNegative
--finput-charset=<cset> Specify the default character set for source files.
+-finput-charset=<cset> Specify the default character set for source files
fexternal-templates
C++ ObjC++
-ffixed-form
-C ObjC
-
-ffixed-line-length-
-C ObjC Joined
-
ffor-scope
C++ ObjC++
Scope of for-init-statement variables is local to the loop
@@ -511,6 +532,10 @@ fgnu-runtime
ObjC ObjC++
Generate code for GNU runtime environment
+fgnu89-inline
+C ObjC Var(flag_gnu89_inline) Init(-1)
+Use traditional GNU semantics for inline functions
+
fguiding-decls
C++ ObjC++
@@ -540,6 +565,10 @@ fimplicit-templates
C++ ObjC++
Emit implicit instantiations of templates
+ffriend-injection
+C++ ObjC++ Var(flag_friend_injection)
+Inject friend functions into enclosing namespace
+
flabels-ok
C++ ObjC++
@@ -567,10 +596,35 @@ C++ ObjC++
fnonnull-objects
C++ ObjC++
+; Generate special '- .cxx_construct' and '- .cxx_destruct' methods
+; to initialize any non-POD ivars in Objective-C++ classes.
+fobjc-call-cxx-cdtors
+ObjC++ Var(flag_objc_call_cxx_cdtors)
+Generate special Objective-C methods to initialize/destroy non-POD C++ ivars, if needed
+
+fobjc-direct-dispatch
+ObjC ObjC++ Var(flag_objc_direct_dispatch)
+Allow fast jumps to the message dispatcher
+
+; Nonzero means that we will allow new ObjC exception syntax (@throw,
+; @try, etc.) in source code.
fobjc-exceptions
-ObjC ObjC++
+ObjC ObjC++ Var(flag_objc_exceptions)
Enable Objective-C exception and synchronization syntax
+fobjc-gc
+ObjC ObjC++ Var(flag_objc_gc)
+Enable garbage collection (GC) in Objective-C/Objective-C++ programs
+
+; Nonzero means that we generate NeXT setjmp based exceptions.
+fobjc-sjlj-exceptions
+ObjC ObjC++ Var(flag_objc_sjlj_exceptions) Init(-1)
+Enable Objective-C setjmp exception handling runtime
+
+fopenmp
+C ObjC C++ ObjC++ Var(flag_openmp)
+Enable OpenMP
+
foperator-names
C++ ObjC++
Recognize C++ kewords like \"compl\" and \"xor\"
@@ -582,6 +636,10 @@ Enable optional diagnostics
fpch-deps
C ObjC C++ ObjC++
+fpch-preprocess
+C ObjC C++ ObjC++
+Look for and use PCH files even when preprocessing
+
fpermissive
C++ ObjC++
Downgrade conformance errors to warnings
@@ -614,9 +672,6 @@ fshort-wchar
C ObjC C++ ObjC++
Force the underlying type for \"wchar_t\" to be \"unsigned short\"
-fshow-column
-C ObjC C++ ObjC++
-
fsigned-bitfields
C ObjC C++ ObjC++
When \"signed\" or \"unsigned\" is not given make the bitfield signed
@@ -640,12 +695,16 @@ C ObjC C++ ObjC++ Joined RejectNegative UInteger
-ftabstop=<number> Distance between tab stops for column reporting
ftemplate-depth-
-C++ ObjC++ Joined RejectNegative UInteger
+C++ ObjC++ Joined RejectNegative UInteger
-ftemplate-depth-<number> Specify maximum template instantiation depth
fthis-is-variable
C++ ObjC++
+fthreadsafe-statics
+C++ ObjC++
+-fno-threadsafe-statics Do not generate thread-safe code for initializing local statics
+
funsigned-bitfields
C ObjC C++ ObjC++
When \"signed\" or \"unsigned\" is not given make the bitfield unsigned
@@ -658,6 +717,14 @@ fuse-cxa-atexit
C++ ObjC++
Use __cxa_atexit to register destructors
+fuse-cxa-get-exception-ptr
+C++ ObjC++
+Use __cxa_get_exception_ptr in exception handling
+
+fvisibility-inlines-hidden
+C++ ObjC++
+Marks all inlined methods as having hidden visibility
+
fvtable-gc
C++ ObjC++
Discard unused virtual functions
@@ -698,6 +765,10 @@ imacros
C ObjC C++ ObjC++ Joined Separate
-imacros <file> Accept definition of macros in <file>
+imultilib
+C ObjC C++ ObjC++ Joined Separate
+-imultilib <dir> Set <dir> to be the multilib include subdirectory
+
include
C ObjC C++ ObjC++ Joined Separate
-include <file> Include the contents of <file> before other files
@@ -714,6 +785,10 @@ isystem
C ObjC C++ ObjC++ Joined Separate
-isystem <dir> Add <dir> to the start of the system include path
+iquote
+C ObjC C++ ObjC++ Joined Separate
+-iquote <dir> Add <dir> to the end of the quote include path
+
iwithprefix
C ObjC C++ ObjC++ Joined Separate
-iwithprefix <dir> Add <dir> to the end of the system include path
@@ -725,6 +800,9 @@ C ObjC C++ ObjC++ Joined Separate
lang-asm
C Undocumented
+lang-fortran
+C Undocumented
+
lang-objc
C ObjC C++ ObjC++ Undocumented
@@ -752,6 +830,10 @@ print-objc-runtime-info
ObjC ObjC++
Generate C header of platform-specific features
+print-pch-checksum
+C ObjC C++ ObjC++
+Print a checksum of the executable for PCH validity checking, and stop
+
remap
C ObjC C++ ObjC++
Remap file names when including files
@@ -824,8 +906,4 @@ w
C ObjC C++ ObjC++
; Documented in common.opt
-fformat-extensions
-C ObjC C++ ObjC++
-Enable FreeBSD format extensions
-
; This comment is to ensure we retain the blank line above.
diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md
index 0fbe00b..d24b32a 100644
--- a/contrib/gcc/config/i386/i386.md
+++ b/contrib/gcc/config/i386/i386.md
@@ -1,6 +1,6 @@
;; GCC machine description for IA-32 and x86-64.
;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004
+;; 2001, 2002, 2003, 2004, 2005, 2006
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;; x86_64 support added by Jan Hubicka
@@ -19,8 +19,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA. */
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA. */
;;
;; The original PO technology requires these to be ordered by speed,
;; so that assigner will pick the fastest.
@@ -66,76 +66,114 @@
(UNSPEC_STACK_ALLOC 11)
(UNSPEC_SET_GOT 12)
(UNSPEC_SSE_PROLOGUE_SAVE 13)
+ (UNSPEC_REG_SAVE 14)
+ (UNSPEC_DEF_CFA 15)
; TLS support
- (UNSPEC_TP 15)
- (UNSPEC_TLS_GD 16)
- (UNSPEC_TLS_LD_BASE 17)
+ (UNSPEC_TP 16)
+ (UNSPEC_TLS_GD 17)
+ (UNSPEC_TLS_LD_BASE 18)
+ (UNSPEC_TLSDESC 19)
; Other random patterns
(UNSPEC_SCAS 20)
- (UNSPEC_SIN 21)
- (UNSPEC_COS 22)
- (UNSPEC_FNSTSW 24)
- (UNSPEC_SAHF 25)
- (UNSPEC_FSTCW 26)
- (UNSPEC_ADD_CARRY 27)
- (UNSPEC_FLDCW 28)
+ (UNSPEC_FNSTSW 21)
+ (UNSPEC_SAHF 22)
+ (UNSPEC_FSTCW 23)
+ (UNSPEC_ADD_CARRY 24)
+ (UNSPEC_FLDCW 25)
+ (UNSPEC_REP 26)
+ (UNSPEC_EH_RETURN 27)
+ (UNSPEC_LD_MPIC 28) ; load_macho_picbase
; For SSE/MMX support:
- (UNSPEC_FIX 30)
- (UNSPEC_MASKMOV 32)
- (UNSPEC_MOVMSK 33)
- (UNSPEC_MOVNT 34)
- (UNSPEC_MOVA 38)
- (UNSPEC_MOVU 39)
- (UNSPEC_SHUFFLE 41)
- (UNSPEC_RCP 42)
- (UNSPEC_RSQRT 43)
- (UNSPEC_SFENCE 44)
- (UNSPEC_NOP 45) ; prevents combiner cleverness
- (UNSPEC_PAVGUSB 49)
- (UNSPEC_PFRCP 50)
- (UNSPEC_PFRCPIT1 51)
- (UNSPEC_PFRCPIT2 52)
- (UNSPEC_PFRSQRT 53)
- (UNSPEC_PFRSQIT1 54)
- (UNSPEC_PSHUFLW 55)
- (UNSPEC_PSHUFHW 56)
- (UNSPEC_MFENCE 59)
- (UNSPEC_LFENCE 60)
- (UNSPEC_PSADBW 61)
- (UNSPEC_ADDSUB 71)
- (UNSPEC_HADD 72)
- (UNSPEC_HSUB 73)
- (UNSPEC_MOVSHDUP 74)
- (UNSPEC_MOVSLDUP 75)
- (UNSPEC_LDQQU 76)
- (UNSPEC_MOVDDUP 77)
+ (UNSPEC_FIX_NOTRUNC 30)
+ (UNSPEC_MASKMOV 31)
+ (UNSPEC_MOVMSK 32)
+ (UNSPEC_MOVNT 33)
+ (UNSPEC_MOVU 34)
+ (UNSPEC_RCP 35)
+ (UNSPEC_RSQRT 36)
+ (UNSPEC_SFENCE 37)
+ (UNSPEC_NOP 38) ; prevents combiner cleverness
+ (UNSPEC_PFRCP 39)
+ (UNSPEC_PFRCPIT1 40)
+ (UNSPEC_PFRCPIT2 41)
+ (UNSPEC_PFRSQRT 42)
+ (UNSPEC_PFRSQIT1 43)
+ (UNSPEC_MFENCE 44)
+ (UNSPEC_LFENCE 45)
+ (UNSPEC_PSADBW 46)
+ (UNSPEC_LDQQU 47)
+
+ ; Generic math support
+ (UNSPEC_COPYSIGN 50)
+ (UNSPEC_IEEE_MIN 51) ; not commutative
+ (UNSPEC_IEEE_MAX 52) ; not commutative
; x87 Floating point
- (UNSPEC_FPATAN 65)
- (UNSPEC_FYL2X 66)
- (UNSPEC_FSCALE 67)
- (UNSPEC_FRNDINT 68)
- (UNSPEC_F2XM1 69)
-
- ; REP instruction
- (UNSPEC_REP 75)
+ (UNSPEC_SIN 60)
+ (UNSPEC_COS 61)
+ (UNSPEC_FPATAN 62)
+ (UNSPEC_FYL2X 63)
+ (UNSPEC_FYL2XP1 64)
+ (UNSPEC_FRNDINT 65)
+ (UNSPEC_FIST 66)
+ (UNSPEC_F2XM1 67)
+
+ ; x87 Rounding
+ (UNSPEC_FRNDINT_FLOOR 70)
+ (UNSPEC_FRNDINT_CEIL 71)
+ (UNSPEC_FRNDINT_TRUNC 72)
+ (UNSPEC_FRNDINT_MASK_PM 73)
+ (UNSPEC_FIST_FLOOR 74)
+ (UNSPEC_FIST_CEIL 75)
+
+ ; x87 Double output FP
+ (UNSPEC_SINCOS_COS 80)
+ (UNSPEC_SINCOS_SIN 81)
+ (UNSPEC_TAN_ONE 82)
+ (UNSPEC_TAN_TAN 83)
+ (UNSPEC_XTRACT_FRACT 84)
+ (UNSPEC_XTRACT_EXP 85)
+ (UNSPEC_FSCALE_FRACT 86)
+ (UNSPEC_FSCALE_EXP 87)
+ (UNSPEC_FPREM_F 88)
+ (UNSPEC_FPREM_U 89)
+ (UNSPEC_FPREM1_F 90)
+ (UNSPEC_FPREM1_U 91)
+
+ ; SSP patterns
+ (UNSPEC_SP_SET 100)
+ (UNSPEC_SP_TEST 101)
+ (UNSPEC_SP_TLS_SET 102)
+ (UNSPEC_SP_TLS_TEST 103)
])
(define_constants
[(UNSPECV_BLOCKAGE 0)
- (UNSPECV_STACK_PROBE 10)
- (UNSPECV_EH_RETURN 13)
- (UNSPECV_EMMS 31)
- (UNSPECV_LDMXCSR 37)
- (UNSPECV_STMXCSR 40)
- (UNSPECV_FEMMS 46)
- (UNSPECV_CLFLUSH 57)
- (UNSPECV_ALIGN 68)
- (UNSPECV_MONITOR 69)
- (UNSPECV_MWAIT 70)
+ (UNSPECV_STACK_PROBE 1)
+ (UNSPECV_EMMS 2)
+ (UNSPECV_LDMXCSR 3)
+ (UNSPECV_STMXCSR 4)
+ (UNSPECV_FEMMS 5)
+ (UNSPECV_CLFLUSH 6)
+ (UNSPECV_ALIGN 7)
+ (UNSPECV_MONITOR 8)
+ (UNSPECV_MWAIT 9)
+ (UNSPECV_CMPXCHG_1 10)
+ (UNSPECV_CMPXCHG_2 11)
+ (UNSPECV_XCHG 12)
+ (UNSPECV_LOCK 13)
+ ])
+
+;; Registers by name.
+(define_constants
+ [(BP_REG 6)
+ (SP_REG 7)
+ (FLAGS_REG 17)
+ (FPSR_REG 18)
+ (DIRFLAG_REG 19)
])
;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
@@ -149,7 +187,7 @@
;; Processor type. This attribute must exactly match the processor_type
;; enumeration in i386.h.
-(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8"
+(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8,nocona,generic32,generic64"
(const (symbol_ref "ix86_tune")))
;; A basic instruction type. Refinements due to arguments to be
@@ -161,22 +199,22 @@
icmp,test,ibr,setcc,icmov,
push,pop,call,callv,leave,
str,cld,
- fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,
- sselog,sseiadd,sseishft,sseimul,
+ fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
+ sselog,sselog1,sseiadd,sseishft,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,
mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
(const_string "other"))
;; Main data type used by the insn
(define_attr "mode"
- "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF"
+ "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF,V1DF"
(const_string "unknown"))
;; The CPU unit operations uses.
(define_attr "unit" "integer,i387,sse,mmx,unknown"
- (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp")
+ (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
(const_string "i387")
- (eq_attr "type" "sselog,sseiadd,sseishft,sseimul,
+ (eq_attr "type" "sselog,sselog1,sseiadd,sseishft,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv")
(const_string "sse")
(eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
@@ -210,7 +248,7 @@
(const_int 1)
]
(symbol_ref "/* Update immediate_length and other attributes! */
- abort(),1")))
+ gcc_unreachable (),1")))
;; The (bounding maximum) length of an instruction address.
(define_attr "length_address" ""
@@ -246,7 +284,7 @@
(const_int 1)
(const_int 0)))
-;; Set when 0f opcode prefix is used.
+;; Set when REX opcode prefix is used.
(define_attr "prefix_rex" ""
(cond [(and (eq_attr "mode" "DI")
(eq_attr "type" "!push,pop,call,callv,leave,ibr"))
@@ -278,8 +316,12 @@
(not (match_operand 0 "memory_operand" "")))
(const_int 0)
(and (eq_attr "type" "imov")
- (and (match_operand 0 "register_operand" "")
- (match_operand 1 "immediate_operand" "")))
+ (ior (and (match_operand 0 "register_operand" "")
+ (match_operand 1 "immediate_operand" ""))
+ (ior (and (match_operand 0 "ax_reg_operand" "")
+ (match_operand 1 "memory_displacement_only_operand" ""))
+ (and (match_operand 0 "memory_displacement_only_operand" "")
+ (match_operand 1 "ax_reg_operand" "")))))
(const_int 0)
(and (eq_attr "type" "call")
(match_operand 0 "constant_call_address_operand" ""))
@@ -291,10 +333,11 @@
(const_int 1)))
;; The (bounding maximum) length of an instruction in bytes.
-;; ??? fistp is in fact fldcw/fistp/fldcw sequence. Later we may want
-;; to split it and compute proper length as for other insns.
+;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences.
+;; Later we may want to split them and compute proper length as for
+;; other insns.
(define_attr "length" ""
- (cond [(eq_attr "type" "other,multi,fistp")
+ (cond [(eq_attr "type" "other,multi,fistp,frndint")
(const_int 16)
(eq_attr "type" "fcmp")
(const_int 4)
@@ -322,6 +365,8 @@
(const_string "none")
(eq_attr "type" "fistp,leave")
(const_string "both")
+ (eq_attr "type" "frndint")
+ (const_string "load")
(eq_attr "type" "push")
(if_then_else (match_operand 1 "memory_operand" "")
(const_string "both")
@@ -351,7 +396,7 @@
(if_then_else (match_operand 1 "constant_call_address_operand" "")
(const_string "none")
(const_string "load"))
- (and (eq_attr "type" "alu1,negnot,ishift1")
+ (and (eq_attr "type" "alu1,negnot,ishift1,sselog1")
(match_operand 1 "memory_operand" ""))
(const_string "both")
(and (match_operand 0 "memory_operand" "")
@@ -365,7 +410,7 @@
"!alu1,negnot,ishift1,
imov,imovx,icmp,test,
fmov,fcmp,fsgn,
- sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,
+ sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,sselog1,
mmx,mmxmov,mmxcmp,mmxcvt")
(match_operand 2 "memory_operand" ""))
(const_string "load")
@@ -396,15 +441,45 @@
(define_attr "fp_int_src" "false,true"
(const_string "false"))
+;; Defines rounding mode of an FP operation.
+
+(define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any"
+ (const_string "any"))
+
;; Describe a user's asm statement.
(define_asm_attributes
[(set_attr "length" "128")
(set_attr "type" "multi")])
+
+;; All x87 floating point modes
+(define_mode_macro X87MODEF [SF DF XF])
+
+;; All integer modes handled by x87 fisttp operator.
+(define_mode_macro X87MODEI [HI SI DI])
+
+;; All integer modes handled by integer x87 operators.
+(define_mode_macro X87MODEI12 [HI SI])
+
+;; All SSE floating point modes
+(define_mode_macro SSEMODEF [SF DF])
+
+;; All integer modes handled by SSE cvtts?2si* operators.
+(define_mode_macro SSEMODEI24 [SI DI])
+
+;; Scheduling descriptions
+
(include "pentium.md")
(include "ppro.md")
(include "k6.md")
(include "athlon.md")
+
+
+;; Operand and operator predicates and constraints
+
+(include "predicates.md")
+(include "constraints.md")
+
;; Compare instructions.
@@ -412,8 +487,21 @@
;; actually generating RTL. The bCOND or sCOND (emitted immediately
;; after the cmp) will actually emit the cmpM.
+(define_expand "cmpti"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "x86_64_general_operand" "")))]
+ "TARGET_64BIT"
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ operands[0] = force_reg (TImode, operands[0]);
+ ix86_compare_op0 = operands[0];
+ ix86_compare_op1 = operands[1];
+ DONE;
+})
+
(define_expand "cmpdi"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "x86_64_general_operand" "")))]
""
@@ -426,7 +514,7 @@
})
(define_expand "cmpsi"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:SI 0 "cmpsi_operand" "")
(match_operand:SI 1 "general_operand" "")))]
""
@@ -439,7 +527,7 @@
})
(define_expand "cmphi"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:HI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" "")))]
""
@@ -452,7 +540,7 @@
})
(define_expand "cmpqi"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:QI 0 "nonimmediate_operand" "")
(match_operand:QI 1 "general_operand" "")))]
"TARGET_QIMODE_MATH"
@@ -465,7 +553,7 @@
})
(define_insn "cmpdi_ccno_1_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
(match_operand:DI 1 "const0_operand" "n,n")))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
@@ -477,7 +565,7 @@
(set_attr "mode" "DI")])
(define_insn "*cmpdi_minus_1_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r")
(match_operand:DI 1 "x86_64_general_operand" "re,mr"))
(const_int 0)))]
@@ -487,14 +575,14 @@
(set_attr "mode" "DI")])
(define_expand "cmpdi_1_rex64"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" "")))]
"TARGET_64BIT"
"")
(define_insn "cmpdi_1_insn_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:DI 0 "nonimmediate_operand" "mr,r")
(match_operand:DI 1 "x86_64_general_operand" "re,mr")))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
@@ -504,7 +592,7 @@
(define_insn "*cmpsi_ccno_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
(match_operand:SI 1 "const0_operand" "n,n")))]
"ix86_match_ccmode (insn, CCNOmode)"
@@ -516,7 +604,7 @@
(set_attr "mode" "SI")])
(define_insn "*cmpsi_minus_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (minus:SI (match_operand:SI 0 "nonimmediate_operand" "rm,r")
(match_operand:SI 1 "general_operand" "ri,mr"))
(const_int 0)))]
@@ -526,14 +614,14 @@
(set_attr "mode" "SI")])
(define_expand "cmpsi_1"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:SI 0 "nonimmediate_operand" "rm,r")
(match_operand:SI 1 "general_operand" "ri,mr")))]
""
"")
(define_insn "*cmpsi_1_insn"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:SI 0 "nonimmediate_operand" "rm,r")
(match_operand:SI 1 "general_operand" "ri,mr")))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
@@ -543,7 +631,7 @@
(set_attr "mode" "SI")])
(define_insn "*cmphi_ccno_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:HI 0 "nonimmediate_operand" "r,?mr")
(match_operand:HI 1 "const0_operand" "n,n")))]
"ix86_match_ccmode (insn, CCNOmode)"
@@ -555,7 +643,7 @@
(set_attr "mode" "HI")])
(define_insn "*cmphi_minus_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (minus:HI (match_operand:HI 0 "nonimmediate_operand" "rm,r")
(match_operand:HI 1 "general_operand" "ri,mr"))
(const_int 0)))]
@@ -565,7 +653,7 @@
(set_attr "mode" "HI")])
(define_insn "*cmphi_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:HI 0 "nonimmediate_operand" "rm,r")
(match_operand:HI 1 "general_operand" "ri,mr")))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
@@ -575,7 +663,7 @@
(set_attr "mode" "HI")])
(define_insn "*cmpqi_ccno_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:QI 0 "nonimmediate_operand" "q,?mq")
(match_operand:QI 1 "const0_operand" "n,n")))]
"ix86_match_ccmode (insn, CCNOmode)"
@@ -587,7 +675,7 @@
(set_attr "mode" "QI")])
(define_insn "*cmpqi_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:QI 0 "nonimmediate_operand" "qm,q")
(match_operand:QI 1 "general_operand" "qi,mq")))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
@@ -597,7 +685,7 @@
(set_attr "mode" "QI")])
(define_insn "*cmpqi_minus_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (minus:QI (match_operand:QI 0 "nonimmediate_operand" "qm,q")
(match_operand:QI 1 "general_operand" "qi,mq"))
(const_int 0)))]
@@ -607,7 +695,7 @@
(set_attr "mode" "QI")])
(define_insn "*cmpqi_ext_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(match_operand:QI 0 "general_operand" "Qm")
(subreg:QI
@@ -621,7 +709,7 @@
(set_attr "mode" "QI")])
(define_insn "*cmpqi_ext_1_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(match_operand:QI 0 "register_operand" "Q")
(subreg:QI
@@ -635,7 +723,7 @@
(set_attr "mode" "QI")])
(define_insn "*cmpqi_ext_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(subreg:QI
(zero_extract:SI
@@ -650,7 +738,7 @@
(set_attr "mode" "QI")])
(define_expand "cmpqi_ext_3"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC
(subreg:QI
(zero_extract:SI
@@ -662,7 +750,7 @@
"")
(define_insn "cmpqi_ext_3_insn"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(subreg:QI
(zero_extract:SI
@@ -676,7 +764,7 @@
(set_attr "mode" "QI")])
(define_insn "cmpqi_ext_3_insn_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(subreg:QI
(zero_extract:SI
@@ -690,7 +778,7 @@
(set_attr "mode" "QI")])
(define_insn "*cmpqi_ext_4"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(subreg:QI
(zero_extract:SI
@@ -713,9 +801,9 @@
;; the old patterns did, but with many more of them.
(define_expand "cmpxf"
- [(set (reg:CC 17)
- (compare:CC (match_operand:XF 0 "cmp_fp_expander_operand" "")
- (match_operand:XF 1 "cmp_fp_expander_operand" "")))]
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:XF 0 "nonmemory_operand" "")
+ (match_operand:XF 1 "nonmemory_operand" "")))]
"TARGET_80387"
{
ix86_compare_op0 = operands[0];
@@ -724,10 +812,10 @@
})
(define_expand "cmpdf"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "")
(match_operand:DF 1 "cmp_fp_expander_operand" "")))]
- "TARGET_80387 || TARGET_SSE2"
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
{
ix86_compare_op0 = operands[0];
ix86_compare_op1 = operands[1];
@@ -735,10 +823,10 @@
})
(define_expand "cmpsf"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:SF 0 "cmp_fp_expander_operand" "")
(match_operand:SF 1 "cmp_fp_expander_operand" "")))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
{
ix86_compare_op0 = operands[0];
ix86_compare_op1 = operands[1];
@@ -751,34 +839,22 @@
;; CCFPmode compare with exceptions
;; CCFPUmode compare with no exceptions
-;; %%% It is an unfortunate fact that ftst has no non-popping variant,
-;; and that fp moves clobber the condition codes, and that there is
-;; currently no way to describe this fact to reg-stack. So there are
-;; no splitters yet for this.
-
-;; %%% YIKES! This scheme does not retain a strong connection between
-;; the real compare and the ultimate cc0 user, so CC_REVERSE does not
-;; work! Only allow tos/mem with tos in op 0.
-;;
-;; Hmm, of course, this is what the actual _hardware_ does. Perhaps
-;; things aren't as bad as they sound...
+;; We may not use "#" to split and emit these, since the REG_DEAD notes
+;; used to manage the reg stack popping would not be preserved.
(define_insn "*cmpfp_0"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
- [(compare:CCFP (match_operand 1 "register_operand" "f")
- (match_operand 2 "const0_operand" "X"))]
- UNSPEC_FNSTSW))]
+ [(compare:CCFP
+ (match_operand 1 "register_operand" "f")
+ (match_operand 2 "const0_operand" "X"))]
+ UNSPEC_FNSTSW))]
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
-{
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "ftst\;fnstsw\t%0\;fstp\t%y0";
- else
- return "ftst\;fnstsw\t%0";
-}
+ "* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
+ (set_attr "unit" "i387")
(set (attr "mode")
(cond [(match_operand:SF 1 "" "")
(const_string "SF")
@@ -787,20 +863,7 @@
]
(const_string "XF")))])
-;; We may not use "#" to split and emit these, since the REG_DEAD notes
-;; used to manage the reg stack popping would not be preserved.
-
-(define_insn "*cmpfp_2_sf"
- [(set (reg:CCFP 18)
- (compare:CCFP
- (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "nonimmediate_operand" "fm")))]
- "TARGET_80387"
- "* return output_fp_compare (insn, operands, 0, 0);"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "SF")])
-
-(define_insn "*cmpfp_2_sf_1"
+(define_insn "*cmpfp_sf"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFP
@@ -808,21 +871,12 @@
(match_operand:SF 2 "nonimmediate_operand" "fm"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "SF")])
-
-(define_insn "*cmpfp_2_df"
- [(set (reg:CCFP 18)
- (compare:CCFP
- (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "nonimmediate_operand" "fm")))]
- "TARGET_80387"
"* return output_fp_compare (insn, operands, 0, 0);"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "DF")])
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387")
+ (set_attr "mode" "SF")])
-(define_insn "*cmpfp_2_df_1"
+(define_insn "*cmpfp_df"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFP
@@ -830,21 +884,12 @@
(match_operand:DF 2 "nonimmediate_operand" "fm"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
+ "* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
+ (set_attr "unit" "i387")
(set_attr "mode" "DF")])
-(define_insn "*cmpfp_2_xf"
- [(set (reg:CCFP 18)
- (compare:CCFP
- (match_operand:XF 0 "register_operand" "f")
- (match_operand:XF 1 "register_operand" "f")))]
- "TARGET_80387"
- "* return output_fp_compare (insn, operands, 0, 0);"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "XF")])
-
-(define_insn "*cmpfp_2_xf_1"
+(define_insn "*cmpfp_xf"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFP
@@ -852,29 +897,12 @@
(match_operand:XF 2 "register_operand" "f"))]
UNSPEC_FNSTSW))]
"TARGET_80387"
- "* return output_fp_compare (insn, operands, 2, 0);"
+ "* return output_fp_compare (insn, operands, 0, 0);"
[(set_attr "type" "multi")
+ (set_attr "unit" "i387")
(set_attr "mode" "XF")])
-(define_insn "*cmpfp_2u"
- [(set (reg:CCFPU 18)
- (compare:CCFPU
- (match_operand 0 "register_operand" "f")
- (match_operand 1 "register_operand" "f")))]
- "TARGET_80387
- && FLOAT_MODE_P (GET_MODE (operands[0]))
- && GET_MODE (operands[0]) == GET_MODE (operands[1])"
- "* return output_fp_compare (insn, operands, 0, 1);"
- [(set_attr "type" "fcmp")
- (set (attr "mode")
- (cond [(match_operand:SF 1 "" "")
- (const_string "SF")
- (match_operand:DF 1 "" "")
- (const_string "DF")
- ]
- (const_string "XF")))])
-
-(define_insn "*cmpfp_2u_1"
+(define_insn "*cmpfp_u"
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFPU
@@ -884,8 +912,9 @@
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
- "* return output_fp_compare (insn, operands, 2, 1);"
+ "* return output_fp_compare (insn, operands, 0, 1);"
[(set_attr "type" "multi")
+ (set_attr "unit" "i387")
(set (attr "mode")
(cond [(match_operand:SF 1 "" "")
(const_string "SF")
@@ -894,95 +923,56 @@
]
(const_string "XF")))])
-;; Patterns to match the SImode-in-memory ficom instructions.
-;;
-;; %%% Play games with accepting gp registers, as otherwise we have to
-;; force them to memory during rtl generation, which is no good. We
-;; can get rid of this once we teach reload to do memory input reloads
-;; via pushes.
-
-(define_insn "*ficom_1"
- [(set (reg:CCFP 18)
- (compare:CCFP
- (match_operand 0 "register_operand" "f,f")
- (float (match_operand:SI 1 "nonimmediate_operand" "m,?r"))))]
- "0 && TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[0]))
- && GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == GET_MODE (operands[0])"
- "#")
-
-;; Split the not-really-implemented gp register case into a
-;; push-op-pop sequence.
-;;
-;; %%% This is most efficient, but am I gonna get in trouble
-;; for separating cc0_setter and cc0_user?
-
-(define_split
- [(set (reg:CCFP 18)
- (compare:CCFP
- (match_operand:SF 0 "register_operand" "")
- (float (match_operand:SI 1 "register_operand" ""))))]
- "0 && TARGET_80387 && reload_completed"
- [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 1))
- (set (reg:CCFP 18) (compare:CCFP (match_dup 0) (match_dup 2)))
- (parallel [(set (match_dup 1) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
- "operands[2] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
- operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);")
+(define_insn "*cmpfp_<mode>"
+ [(set (match_operand:HI 0 "register_operand" "=a")
+ (unspec:HI
+ [(compare:CCFP
+ (match_operand 1 "register_operand" "f")
+ (match_operator 3 "float_operator"
+ [(match_operand:X87MODEI12 2 "memory_operand" "m")]))]
+ UNSPEC_FNSTSW))]
+ "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
+ "* return output_fp_compare (insn, operands, 0, 0);"
+ [(set_attr "type" "multi")
+ (set_attr "unit" "i387")
+ (set_attr "fp_int_src" "true")
+ (set_attr "mode" "<MODE>")])
;; FP compares, step 2
;; Move the fpsw to ax.
-(define_insn "*x86_fnstsw_1"
+(define_insn "x86_fnstsw_1"
[(set (match_operand:HI 0 "register_operand" "=a")
- (unspec:HI [(reg 18)] UNSPEC_FNSTSW))]
+ (unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))]
"TARGET_80387"
"fnstsw\t%0"
[(set_attr "length" "2")
(set_attr "mode" "SI")
- (set_attr "unit" "i387")
- (set_attr "ppro_uops" "few")])
+ (set_attr "unit" "i387")])
;; FP compares, step 3
;; Get ax into flags, general case.
(define_insn "x86_sahf_1"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(unspec:CC [(match_operand:HI 0 "register_operand" "a")] UNSPEC_SAHF))]
"!TARGET_64BIT"
"sahf"
[(set_attr "length" "1")
(set_attr "athlon_decode" "vector")
- (set_attr "mode" "SI")
- (set_attr "ppro_uops" "one")])
+ (set_attr "mode" "SI")])
;; Pentium Pro can do steps 1 through 3 in one go.
-(define_insn "*cmpfp_i"
- [(set (reg:CCFP 17)
- (compare:CCFP (match_operand 0 "register_operand" "f")
- (match_operand 1 "register_operand" "f")))]
- "TARGET_80387 && TARGET_CMOVE
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
- && FLOAT_MODE_P (GET_MODE (operands[0]))
- && GET_MODE (operands[0]) == GET_MODE (operands[0])"
- "* return output_fp_compare (insn, operands, 1, 0);"
- [(set_attr "type" "fcmp")
- (set (attr "mode")
- (cond [(match_operand:SF 1 "" "")
- (const_string "SF")
- (match_operand:DF 1 "" "")
- (const_string "DF")
- ]
- (const_string "XF")))
- (set_attr "athlon_decode" "vector")])
-
-(define_insn "*cmpfp_i_sse"
- [(set (reg:CCFP 17)
- (compare:CCFP (match_operand 0 "register_operand" "f#x,x#f")
- (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
- "TARGET_80387
+(define_insn "*cmpfp_i_mixed"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP (match_operand 0 "register_operand" "f,x")
+ (match_operand 1 "nonimmediate_operand" "f,xm")))]
+ "TARGET_MIX_SSE_I387
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
- && GET_MODE (operands[0]) == GET_MODE (operands[0])"
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "fcmp,ssecomi")
(set (attr "mode")
@@ -991,12 +981,13 @@
(const_string "DF")))
(set_attr "athlon_decode" "vector")])
-(define_insn "*cmpfp_i_sse_only"
- [(set (reg:CCFP 17)
+(define_insn "*cmpfp_i_sse"
+ [(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "x")
(match_operand 1 "nonimmediate_operand" "xm")))]
- "SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
- && GET_MODE (operands[0]) == GET_MODE (operands[0])"
+ "TARGET_SSE_MATH
+ && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "ssecomi")
(set (attr "mode")
@@ -1005,15 +996,15 @@
(const_string "DF")))
(set_attr "athlon_decode" "vector")])
-(define_insn "*cmpfp_iu"
- [(set (reg:CCFPU 17)
- (compare:CCFPU (match_operand 0 "register_operand" "f")
- (match_operand 1 "register_operand" "f")))]
+(define_insn "*cmpfp_i_i387"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP (match_operand 0 "register_operand" "f")
+ (match_operand 1 "register_operand" "f")))]
"TARGET_80387 && TARGET_CMOVE
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
+ && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
&& FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
- "* return output_fp_compare (insn, operands, 1, 1);"
+ "* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "fcmp")
(set (attr "mode")
(cond [(match_operand:SF 1 "" "")
@@ -1024,11 +1015,11 @@
(const_string "XF")))
(set_attr "athlon_decode" "vector")])
-(define_insn "*cmpfp_iu_sse"
- [(set (reg:CCFPU 17)
- (compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f")
- (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
- "TARGET_80387
+(define_insn "*cmpfp_iu_mixed"
+ [(set (reg:CCFPU FLAGS_REG)
+ (compare:CCFPU (match_operand 0 "register_operand" "f,x")
+ (match_operand 1 "nonimmediate_operand" "f,xm")))]
+ "TARGET_MIX_SSE_I387
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);"
@@ -1039,11 +1030,12 @@
(const_string "DF")))
(set_attr "athlon_decode" "vector")])
-(define_insn "*cmpfp_iu_sse_only"
- [(set (reg:CCFPU 17)
+(define_insn "*cmpfp_iu_sse"
+ [(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "x")
(match_operand 1 "nonimmediate_operand" "xm")))]
- "SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
+ "TARGET_SSE_MATH
+ && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);"
[(set_attr "type" "ssecomi")
@@ -1052,6 +1044,25 @@
(const_string "SF")
(const_string "DF")))
(set_attr "athlon_decode" "vector")])
+
+(define_insn "*cmpfp_iu_387"
+ [(set (reg:CCFPU FLAGS_REG)
+ (compare:CCFPU (match_operand 0 "register_operand" "f")
+ (match_operand 1 "register_operand" "f")))]
+ "TARGET_80387 && TARGET_CMOVE
+ && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
+ && FLOAT_MODE_P (GET_MODE (operands[0]))
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])"
+ "* return output_fp_compare (insn, operands, 1, 1);"
+ [(set_attr "type" "fcmp")
+ (set (attr "mode")
+ (cond [(match_operand:SF 1 "" "")
+ (const_string "SF")
+ (match_operand:DF 1 "" "")
+ (const_string "DF")
+ ]
+ (const_string "XF")))
+ (set_attr "athlon_decode" "vector")])
;; Move instructions.
@@ -1100,9 +1111,9 @@
(define_insn "*popsi1_epilogue"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
- (mem:SI (reg:SI 7)))
- (set (reg:SI 7)
- (plus:SI (reg:SI 7) (const_int 4)))
+ (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int 4)))
(clobber (mem:BLK (scratch)))]
"!TARGET_64BIT"
"pop{l}\t%0"
@@ -1111,9 +1122,9 @@
(define_insn "popsi1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
- (mem:SI (reg:SI 7)))
- (set (reg:SI 7)
- (plus:SI (reg:SI 7) (const_int 4)))]
+ (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int 4)))]
"!TARGET_64BIT"
"pop{l}\t%0"
[(set_attr "type" "pop")
@@ -1122,7 +1133,7 @@
(define_insn "*movsi_xor"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "const0_operand" "i"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
"xor{l}\t{%0, %0|%0, %0}"
[(set_attr "type" "alu1")
@@ -1132,7 +1143,7 @@
(define_insn "*movsi_or"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "immediate_operand" "i"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& operands[1] == constm1_rtx
&& (TARGET_PENTIUM || optimize_size)"
@@ -1145,56 +1156,36 @@
(set_attr "length_immediate" "1")])
(define_insn "*movsi_1"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!rm,!*y,!*Y,!rm,!*Y")
- (match_operand:SI 1 "general_operand" "rinm,rin,*y,*y,rm,*Y,*Y,rm"))]
- "(TARGET_INTER_UNIT_MOVES || optimize_size)
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ [(set (match_operand:SI 0 "nonimmediate_operand"
+ "=r ,m ,*y,*y,?rm,?*y,*x,*x,?r,m ,?*Y,*x")
+ (match_operand:SI 1 "general_operand"
+ "rinm,rin,C ,*y,*y ,rm ,C ,*x,*Y,*x,r ,m "))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
{
- case TYPE_SSEMOV:
+ case TYPE_SSELOG1:
if (get_attr_mode (insn) == MODE_TI)
- return "movdqa\t{%1, %0|%0, %1}";
- return "movd\t{%1, %0|%0, %1}";
+ return "pxor\t%0, %0";
+ return "xorps\t%0, %0";
- case TYPE_MMXMOV:
- if (get_attr_mode (insn) == MODE_DI)
- return "movq\t{%1, %0|%0, %1}";
- return "movd\t{%1, %0|%0, %1}";
-
- case TYPE_LEA:
- return "lea{l}\t{%1, %0|%0, %1}";
-
- default:
- if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
- abort();
- return "mov{l}\t{%1, %0|%0, %1}";
- }
-}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "2,3,4")
- (const_string "mmxmov")
- (eq_attr "alternative" "5,6,7")
- (const_string "ssemov")
- (and (ne (symbol_ref "flag_pic") (const_int 0))
- (match_operand:SI 1 "symbolic_operand" ""))
- (const_string "lea")
- ]
- (const_string "imov")))
- (set_attr "mode" "SI,SI,DI,SI,SI,TI,SI,SI")])
-
-(define_insn "*movsi_1_nointernunit"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!m,!*y,!*Y,!m,!*Y")
- (match_operand:SI 1 "general_operand" "rinm,rin,*y,*y,m,*Y,*Y,m"))]
- "(!TARGET_INTER_UNIT_MOVES && !optimize_size)
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (get_attr_type (insn))
- {
case TYPE_SSEMOV:
- if (get_attr_mode (insn) == MODE_TI)
- return "movdqa\t{%1, %0|%0, %1}";
- return "movd\t{%1, %0|%0, %1}";
+ switch (get_attr_mode (insn))
+ {
+ case MODE_TI:
+ return "movdqa\t{%1, %0|%0, %1}";
+ case MODE_V4SF:
+ return "movaps\t{%1, %0|%0, %1}";
+ case MODE_SI:
+ return "movd\t{%1, %0|%0, %1}";
+ case MODE_SF:
+ return "movss\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+
+ case TYPE_MMXADD:
+ return "pxor\t%0, %0";
case TYPE_MMXMOV:
if (get_attr_mode (insn) == MODE_DI)
@@ -1205,22 +1196,36 @@
return "lea{l}\t{%1, %0|%0, %1}";
default:
- if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
- abort();
+ gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
return "mov{l}\t{%1, %0|%0, %1}";
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "2,3,4")
+ (cond [(eq_attr "alternative" "2")
+ (const_string "mmxadd")
+ (eq_attr "alternative" "3,4,5")
(const_string "mmxmov")
- (eq_attr "alternative" "5,6,7")
+ (eq_attr "alternative" "6")
+ (const_string "sselog1")
+ (eq_attr "alternative" "7,8,9,10,11")
(const_string "ssemov")
- (and (ne (symbol_ref "flag_pic") (const_int 0))
- (match_operand:SI 1 "symbolic_operand" ""))
+ (match_operand:DI 1 "pic_32bit_operand" "")
(const_string "lea")
]
(const_string "imov")))
- (set_attr "mode" "SI,SI,DI,SI,SI,TI,SI,SI")])
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "2,3")
+ (const_string "DI")
+ (eq_attr "alternative" "6,7")
+ (if_then_else
+ (eq (symbol_ref "TARGET_SSE2") (const_int 0))
+ (const_string "V4SF")
+ (const_string "TI"))
+ (and (eq_attr "alternative" "8,9,10,11")
+ (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
+ (const_string "SF")
+ ]
+ (const_string "SI")))])
;; Stores and loads of ax to arbitrary constant address.
;; We fake an second form of instruction to force reload to load address
@@ -1263,8 +1268,7 @@
[(set_attr "type" "imov")
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "ppro_uops" "few")])
+ (set_attr "athlon_decode" "vector")])
(define_expand "movhi"
[(set (match_operand:HI 0 "nonimmediate_operand" "")
@@ -1273,14 +1277,12 @@
"ix86_expand_move (HImode, operands); DONE;")
(define_insn "*pushhi2"
- [(set (match_operand:HI 0 "push_operand" "=<,<")
- (match_operand:HI 1 "general_no_elim_operand" "n,r*m"))]
+ [(set (match_operand:HI 0 "push_operand" "=X")
+ (match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
"!TARGET_64BIT"
- "@
- push{w}\t{|WORD PTR }%1
- push{w}\t%1"
+ "push{l}\t%k1"
[(set_attr "type" "push")
- (set_attr "mode" "HI")])
+ (set_attr "mode" "SI")])
;; For 64BIT abi we always round up to 8 bytes.
(define_insn "*pushhi2_rex64"
@@ -1289,7 +1291,7 @@
"TARGET_64BIT"
"push{q}\t%q1"
[(set_attr "type" "push")
- (set_attr "mode" "QI")])
+ (set_attr "mode" "DI")])
(define_insn "*movhi_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
@@ -1310,7 +1312,9 @@
}
}
[(set (attr "type")
- (cond [(and (eq_attr "alternative" "0")
+ (cond [(ne (symbol_ref "optimize_size") (const_int 0))
+ (const_string "imov")
+ (and (eq_attr "alternative" "0")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_HIMODE_MATH")
@@ -1381,8 +1385,7 @@
[(set_attr "type" "imov")
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "ppro_uops" "few")])
+ (set_attr "athlon_decode" "vector")])
(define_insn "*swaphi_2"
[(set (match_operand:HI 0 "register_operand" "+r")
@@ -1394,8 +1397,7 @@
[(set_attr "type" "imov")
(set_attr "mode" "HI")
(set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "ppro_uops" "few")])
+ (set_attr "athlon_decode" "vector")])
(define_expand "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
@@ -1419,7 +1421,7 @@
(define_insn "*movstricthi_xor"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
(match_operand:HI 1 "const0_operand" "i"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ((!TARGET_USE_MOV0 && !TARGET_PARTIAL_REG_STALL) || optimize_size)"
"xor{w}\t{%0, %0|%0, %0}"
@@ -1434,18 +1436,16 @@
"ix86_expand_move (QImode, operands); DONE;")
;; emit_push_insn when it calls move_by_pieces requires an insn to
-;; "push a byte". But actually we use pushw, which has the effect
-;; of rounding the amount pushed up to a halfword.
+;; "push a byte". But actually we use pushl, which has the effect
+;; of rounding the amount pushed up to a word.
(define_insn "*pushqi2"
- [(set (match_operand:QI 0 "push_operand" "=X,X")
- (match_operand:QI 1 "nonmemory_no_elim_operand" "n,r"))]
+ [(set (match_operand:QI 0 "push_operand" "=X")
+ (match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))]
"!TARGET_64BIT"
- "@
- push{w}\t{|word ptr }%1
- push{w}\t%w1"
+ "push{l}\t%k1"
[(set_attr "type" "push")
- (set_attr "mode" "HI")])
+ (set_attr "mode" "SI")])
;; For 64BIT abi we always round up to 8 bytes.
(define_insn "*pushqi2_rex64"
@@ -1454,7 +1454,7 @@
"TARGET_64BIT"
"push{q}\t%q1"
[(set_attr "type" "push")
- (set_attr "mode" "QI")])
+ (set_attr "mode" "DI")])
;; Situation is quite tricky about when to choose full sized (SImode) move
;; over QImode moves. For Q_REG -> Q_REG move we use full size only for
@@ -1474,8 +1474,7 @@
switch (get_attr_type (insn))
{
case TYPE_IMOVX:
- if (!ANY_QI_REG_P (operands[1]) && GET_CODE (operands[1]) != MEM)
- abort ();
+ gcc_assert (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM);
return "movz{bl|x}\t{%1, %k0|%k0, %1}";
default:
if (get_attr_mode (insn) == MODE_SI)
@@ -1485,7 +1484,12 @@
}
}
[(set (attr "type")
- (cond [(and (eq_attr "alternative" "3")
+ (cond [(and (eq_attr "alternative" "5")
+ (not (match_operand:QI 1 "aligned_operand" "")))
+ (const_string "imovx")
+ (ne (symbol_ref "optimize_size") (const_int 0))
+ (const_string "imov")
+ (and (eq_attr "alternative" "3")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_QIMODE_MATH")
@@ -1507,13 +1511,17 @@
(eq_attr "type" "imovx")
(const_string "SI")
(and (eq_attr "type" "imov")
- (and (eq_attr "alternative" "0,1,2")
- (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
- (const_int 0))))
+ (and (eq_attr "alternative" "0,1")
+ (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
+ (const_int 0))
+ (and (eq (symbol_ref "optimize_size")
+ (const_int 0))
+ (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
+ (const_int 0))))))
(const_string "SI")
;; Avoid partial register stalls when not using QImode arithmetic
(and (eq_attr "type" "imov")
- (and (eq_attr "alternative" "0,1,2")
+ (and (eq_attr "alternative" "0,1")
(and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_QIMODE_MATH")
@@ -1531,8 +1539,7 @@
rtx op0, op1, op2;
op0 = operands[0]; op1 = operands[1]; op2 = operands[2];
- if (reg_overlap_mentioned_p (op2, op0))
- abort ();
+ gcc_assert (!reg_overlap_mentioned_p (op2, op0));
if (! q_regs_operand (op1, QImode))
{
emit_insn (gen_movqi (op2, op1));
@@ -1552,8 +1559,7 @@
[(set_attr "type" "imov")
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "ppro_uops" "few")])
+ (set_attr "athlon_decode" "vector")])
(define_insn "*swapqi_2"
[(set (match_operand:QI 0 "register_operand" "+q")
@@ -1565,8 +1571,7 @@
[(set_attr "type" "imov")
(set_attr "mode" "QI")
(set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "ppro_uops" "few")])
+ (set_attr "athlon_decode" "vector")])
(define_expand "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
@@ -1590,7 +1595,7 @@
(define_insn "*movstrictqi_xor"
[(set (strict_low_part (match_operand:QI 0 "q_regs_operand" "+q"))
(match_operand:QI 1 "const0_operand" "i"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed && (!TARGET_USE_MOV0 || optimize_size)"
"xor{b}\t{%0, %0|%0, %0}"
[(set_attr "type" "alu1")
@@ -1702,6 +1707,16 @@
(set_attr "memory" "load")
(set_attr "mode" "QI")])
+(define_insn "*movdi_extzv_1"
+ [(set (match_operand:DI 0 "register_operand" "=R")
+ (zero_extract:DI (match_operand 1 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8)))]
+ "TARGET_64BIT"
+ "movz{bl|x}\t{%h1, %k0|%k0, %h1}"
+ [(set_attr "type" "imovx")
+ (set_attr "mode" "DI")])
+
(define_insn "*movsi_extzv_1"
[(set (match_operand:SI 0 "register_operand" "=R")
(zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
@@ -1808,7 +1823,7 @@
"!TARGET_64BIT"
"#")
-(define_insn "pushdi2_rex64"
+(define_insn "*pushdi2_rex64"
[(set (match_operand:DI 0 "push_operand" "=<,!<")
(match_operand:DI 1 "general_no_elim_operand" "re*m,n"))]
"TARGET_64BIT"
@@ -1834,6 +1849,7 @@
;; We need to define this as both peepholer and splitter for case
;; peephole2 pass is not run.
+;; "&& 1" is needed to keep it from matching the previous pattern.
(define_peephole2
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
@@ -1851,7 +1867,7 @@
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)
+ ? flow2_completed : reload_completed)
&& !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
[(set (match_dup 0) (match_dup 1))
@@ -1873,9 +1889,9 @@
(define_insn "*popdi1_epilogue_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
- (mem:DI (reg:DI 7)))
- (set (reg:DI 7)
- (plus:DI (reg:DI 7) (const_int 8)))
+ (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG)
+ (plus:DI (reg:DI SP_REG) (const_int 8)))
(clobber (mem:BLK (scratch)))]
"TARGET_64BIT"
"pop{q}\t%0"
@@ -1884,9 +1900,9 @@
(define_insn "popdi1"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
- (mem:DI (reg:DI 7)))
- (set (reg:DI 7)
- (plus:DI (reg:DI 7) (const_int 8)))]
+ (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG)
+ (plus:DI (reg:DI SP_REG) (const_int 8)))]
"TARGET_64BIT"
"pop{q}\t%0"
[(set_attr "type" "pop")
@@ -1895,7 +1911,7 @@
(define_insn "*movdi_xor_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "const0_operand" "i"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && (!TARGET_USE_MOV0 || optimize_size)
&& reload_completed"
"xor{l}\t{%k0, %k0|%k0, %k0}"
@@ -1906,7 +1922,7 @@
(define_insn "*movdi_or_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "const_int_operand" "i"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && (TARGET_PENTIUM || optimize_size)
&& reload_completed
&& operands[1] == constm1_rtx"
@@ -1919,20 +1935,27 @@
(set_attr "length_immediate" "1")])
(define_insn "*movdi_2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,!m*y,!*y,!m,!*Y,!*Y")
- (match_operand:DI 1 "general_operand" "riFo,riF,*y,m,*Y,*Y,m"))]
- "!TARGET_64BIT
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ [(set (match_operand:DI 0 "nonimmediate_operand"
+ "=r ,o ,*y,m*y,*y,*Y,m ,*Y,*Y,*x,m ,*x,*x")
+ (match_operand:DI 1 "general_operand"
+ "riFo,riF,C ,*y ,m ,C ,*Y,*Y,m ,C ,*x,*x,m "))]
+ "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"@
#
#
+ pxor\t%0, %0
movq\t{%1, %0|%0, %1}
movq\t{%1, %0|%0, %1}
+ pxor\t%0, %0
movq\t{%1, %0|%0, %1}
movdqa\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "*,*,mmx,mmx,ssemov,ssemov,ssemov")
- (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI")])
+ movq\t{%1, %0|%0, %1}
+ xorps\t%0, %0
+ movlps\t{%1, %0|%0, %1}
+ movaps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "*,*,mmx,mmxmov,mmxmov,sselog1,ssemov,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov")
+ (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")])
(define_split
[(set (match_operand:DI 0 "push_operand" "")
@@ -1953,14 +1976,19 @@
"ix86_split_long_move (operands); DONE;")
(define_insn "*movdi_1_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,mr,!mr,!*y,!rm,!*y,!*Y,!rm,!*Y")
- (match_operand:DI 1 "general_operand" "Z,rem,i,re,n,*y,*y,rm,*Y,*Y,rm"))]
- "TARGET_64BIT
- && (TARGET_INTER_UNIT_MOVES || optimize_size)
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ [(set (match_operand:DI 0 "nonimmediate_operand"
+ "=r,r ,r,m ,!m,*y,*y,?rm,?*y,*x,*x,?rm,?*x,?*x,?*y")
+ (match_operand:DI 1 "general_operand"
+ "Z ,rem,i,re,n ,C ,*y,*y ,rm ,C ,*x,*x ,rm ,*y ,*x"))]
+ "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
{
+ case TYPE_SSECVT:
+ if (which_alternative == 13)
+ return "movq2dq\t{%1, %0|%0, %1}";
+ else
+ return "movdq2q\t{%1, %0|%0, %1}";
case TYPE_SSEMOV:
if (get_attr_mode (insn) == MODE_TI)
return "movdqa\t{%1, %0|%0, %1}";
@@ -1971,59 +1999,15 @@
if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
return "movd\t{%1, %0|%0, %1}";
return "movq\t{%1, %0|%0, %1}";
+ case TYPE_SSELOG1:
+ case TYPE_MMXADD:
+ return "pxor\t%0, %0";
case TYPE_MULTI:
return "#";
case TYPE_LEA:
return "lea{q}\t{%a1, %0|%0, %a1}";
default:
- if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
- abort ();
- if (get_attr_mode (insn) == MODE_SI)
- return "mov{l}\t{%k1, %k0|%k0, %k1}";
- else if (which_alternative == 2)
- return "movabs{q}\t{%1, %0|%0, %1}";
- else
- return "mov{q}\t{%1, %0|%0, %1}";
- }
-}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "5,6,7")
- (const_string "mmxmov")
- (eq_attr "alternative" "8,9,10")
- (const_string "ssemov")
- (eq_attr "alternative" "4")
- (const_string "multi")
- (and (ne (symbol_ref "flag_pic") (const_int 0))
- (match_operand:DI 1 "symbolic_operand" ""))
- (const_string "lea")
- ]
- (const_string "imov")))
- (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*")
- (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*")
- (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,TI,DI,DI")])
-
-(define_insn "*movdi_1_rex64_nointerunit"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,mr,!mr,!*y,!m,!*y,!*Y,!m,!*Y")
- (match_operand:DI 1 "general_operand" "Z,rem,i,re,n,*y,*y,m,*Y,*Y,m"))]
- "TARGET_64BIT
- && (!TARGET_INTER_UNIT_MOVES && !optimize_size)
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_SSEMOV:
- if (get_attr_mode (insn) == MODE_TI)
- return "movdqa\t{%1, %0|%0, %1}";
- /* FALLTHRU */
- case TYPE_MMXMOV:
- return "movq\t{%1, %0|%0, %1}";
- case TYPE_MULTI:
- return "#";
- case TYPE_LEA:
- return "lea{q}\t{%a1, %0|%0, %a1}";
- default:
- if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
- abort ();
+ gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
if (get_attr_mode (insn) == MODE_SI)
return "mov{l}\t{%k1, %k0|%k0, %k1}";
else if (which_alternative == 2)
@@ -2033,20 +2017,25 @@
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "5,6,7")
+ (cond [(eq_attr "alternative" "5")
+ (const_string "mmxadd")
+ (eq_attr "alternative" "6,7,8")
(const_string "mmxmov")
- (eq_attr "alternative" "8,9,10")
+ (eq_attr "alternative" "9")
+ (const_string "sselog1")
+ (eq_attr "alternative" "10,11,12")
(const_string "ssemov")
+ (eq_attr "alternative" "13,14")
+ (const_string "ssecvt")
(eq_attr "alternative" "4")
(const_string "multi")
- (and (ne (symbol_ref "flag_pic") (const_int 0))
- (match_operand:DI 1 "symbolic_operand" ""))
+ (match_operand:DI 1 "pic_32bit_operand" "")
(const_string "lea")
]
(const_string "imov")))
- (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*")
- (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*")
- (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,TI,DI,DI")])
+ (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*")
+ (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*")
+ (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI")])
;; Stores and loads of ax to arbitrary constant address.
;; We fake an second form of instruction to force reload to load address
@@ -2094,6 +2083,7 @@
;; We need to define this as both peepholer and splitter for case
;; peephole2 pass is not run.
+;; "&& 1" is needed to keep it from matching the previous pattern.
(define_peephole2
[(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
@@ -2107,7 +2097,7 @@
[(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)
+ ? flow2_completed : reload_completed)
&& !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
[(set (match_dup 2) (match_dup 3))
@@ -2124,8 +2114,105 @@
[(set_attr "type" "imov")
(set_attr "mode" "DI")
(set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "ppro_uops" "few")])
+ (set_attr "athlon_decode" "vector")])
+
+(define_expand "movti"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE || TARGET_64BIT"
+{
+ if (TARGET_64BIT)
+ ix86_expand_move (TImode, operands);
+ else
+ ix86_expand_vector_move (TImode, operands);
+ DONE;
+})
+
+(define_insn "*movti_internal"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
+ "TARGET_SSE && !TARGET_64BIT
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "xorps\t%0, %0";
+ else
+ return "pxor\t%0, %0";
+ case 1:
+ case 2:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "movaps\t{%1, %0|%0, %1}";
+ else
+ return "movdqa\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "sselog1,ssemov,ssemov")
+ (set (attr "mode")
+ (cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0))
+ (ne (symbol_ref "optimize_size") (const_int 0)))
+ (const_string "V4SF")
+ (and (eq_attr "alternative" "2")
+ (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
+ (const_int 0)))
+ (const_string "V4SF")]
+ (const_string "TI")))])
+
+(define_insn "*movti_rex64"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm")
+ (match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))]
+ "TARGET_64BIT
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ return "#";
+ case 2:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "xorps\t%0, %0";
+ else
+ return "pxor\t%0, %0";
+ case 3:
+ case 4:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "movaps\t{%1, %0|%0, %1}";
+ else
+ return "movdqa\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "2,3")
+ (if_then_else
+ (ne (symbol_ref "optimize_size")
+ (const_int 0))
+ (const_string "V4SF")
+ (const_string "TI"))
+ (eq_attr "alternative" "4")
+ (if_then_else
+ (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
+ (const_int 0))
+ (ne (symbol_ref "optimize_size")
+ (const_int 0)))
+ (const_string "V4SF")
+ (const_string "TI"))]
+ (const_string "DI")))])
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "general_operand" ""))]
+ "reload_completed && !SSE_REG_P (operands[0])
+ && !SSE_REG_P (operands[1])"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
(define_expand "movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "")
@@ -2135,38 +2222,28 @@
(define_insn "*pushsf"
[(set (match_operand:SF 0 "push_operand" "=<,<,<")
- (match_operand:SF 1 "general_no_elim_operand" "f#rx,rFm#fx,x#rf"))]
+ (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
"!TARGET_64BIT"
{
- switch (which_alternative)
- {
- case 1:
- return "push{l}\t%1";
-
- default:
- /* This insn should be already split before reg-stack. */
- abort ();
- }
+ /* Anything else should be already split before reg-stack. */
+ gcc_assert (which_alternative == 1);
+ return "push{l}\t%1";
}
[(set_attr "type" "multi,push,multi")
+ (set_attr "unit" "i387,*,*")
(set_attr "mode" "SF,SI,SF")])
(define_insn "*pushsf_rex64"
[(set (match_operand:SF 0 "push_operand" "=X,X,X")
- (match_operand:SF 1 "nonmemory_no_elim_operand" "f#rx,rF#fx,x#rf"))]
+ (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
"TARGET_64BIT"
{
- switch (which_alternative)
- {
- case 1:
- return "push{q}\t%q1";
-
- default:
- /* This insn should be already split before reg-stack. */
- abort ();
- }
+ /* Anything else should be already split before reg-stack. */
+ gcc_assert (which_alternative == 1);
+ return "push{q}\t%q1";
}
[(set_attr "type" "multi,push,multi")
+ (set_attr "unit" "i387,*,*")
(set_attr "mode" "SF,DI,SF")])
(define_split
@@ -2185,21 +2262,22 @@
[(set (match_operand:SF 0 "push_operand" "")
(match_operand:SF 1 "any_fp_register_operand" ""))]
"!TARGET_64BIT"
- [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4)))
- (set (mem:SF (reg:SI 7)) (match_dup 1))])
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (set (mem:SF (reg:SI SP_REG)) (match_dup 1))])
(define_split
[(set (match_operand:SF 0 "push_operand" "")
(match_operand:SF 1 "any_fp_register_operand" ""))]
"TARGET_64BIT"
- [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8)))
- (set (mem:SF (reg:DI 7)) (match_dup 1))])
+ [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
+ (set (mem:SF (reg:DI SP_REG)) (match_dup 1))])
(define_insn "*movsf_1"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f#xr,m,f#xr,r#xf,m,x#rf,x#rf,x#rf,m,!*y,!rm,!*y")
- (match_operand:SF 1 "general_operand" "fm#rx,f#rx,G,rmF#fx,Fr#fx,C,x,xm#rf,x#rf,rm,*y,*y"))]
- "(TARGET_INTER_UNIT_MOVES || optimize_size)
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ [(set (match_operand:SF 0 "nonimmediate_operand"
+ "=f,m ,f,r ,m ,x,x,x ,m ,!*y,!rm,!*y")
+ (match_operand:SF 1 "general_operand"
+ "fm,f,G ,rmF,Fr,C ,x ,xm,x,rm ,*y ,*y"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (reload_in_progress || reload_completed
|| (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
|| GET_CODE (operands[1]) != CONST_DOUBLE
@@ -2208,13 +2286,7 @@
switch (which_alternative)
{
case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp\t%y0";
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
+ return output_387_reg_move (insn, operands);
case 1:
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
@@ -2250,10 +2322,10 @@
return "movq\t{%1, %0|%0, %1}";
default:
- abort();
+ gcc_unreachable ();
}
}
- [(set_attr "type" "fmov,fmov,fmov,imov,imov,ssemov,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
+ [(set_attr "type" "fmov,fmov,fmov,imov,imov,sselog1,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
(set (attr "mode")
(cond [(eq_attr "alternative" "3,4,9,10")
(const_string "SI")
@@ -2281,106 +2353,7 @@
(if_then_else
(ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
(const_int 0))
- (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "SF"))
- (eq_attr "alternative" "11")
- (const_string "DI")]
- (const_string "SF")))])
-
-(define_insn "*movsf_1_nointerunit"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f#xr,m,f#xr,r#xf,m,x#rf,x#rf,x#rf,m,!*y,!m,!*y")
- (match_operand:SF 1 "general_operand" "fm#rx,f#rx,G,rmF#fx,Fr#fx,C,x,xm#rf,x#rf,m,*y,*y"))]
- "(!TARGET_INTER_UNIT_MOVES && !optimize_size)
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
- && (reload_in_progress || reload_completed
- || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
- || GET_CODE (operands[1]) != CONST_DOUBLE
- || memory_operand (operands[0], SFmode))"
-{
- switch (which_alternative)
- {
- case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- {
- if (REGNO (operands[0]) == FIRST_STACK_REG
- && TARGET_USE_FFREEP)
- return "ffreep\t%y0";
- return "fstp\t%y0";
- }
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
-
- case 1:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
-
- case 2:
- return standard_80387_constant_opcode (operands[1]);
-
- case 3:
- case 4:
- return "mov{l}\t{%1, %0|%0, %1}";
- case 5:
- if (get_attr_mode (insn) == MODE_TI)
- return "pxor\t%0, %0";
- else
- return "xorps\t%0, %0";
- case 6:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movss\t{%1, %0|%0, %1}";
- case 7:
- case 8:
- return "movss\t{%1, %0|%0, %1}";
-
- case 9:
- case 10:
- return "movd\t{%1, %0|%0, %1}";
-
- case 11:
- return "movq\t{%1, %0|%0, %1}";
-
- default:
- abort();
- }
-}
- [(set_attr "type" "fmov,fmov,fmov,imov,imov,ssemov,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "3,4,9,10")
- (const_string "SI")
- (eq_attr "alternative" "5")
- (if_then_else
- (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
- (const_int 0))
- (ne (symbol_ref "TARGET_SSE2")
- (const_int 0)))
- (eq (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "TI")
- (const_string "V4SF"))
- /* For architectures resolving dependencies on
- whole SSE registers use APS move to break dependency
- chains, otherwise use short move to avoid extra work.
-
- Do the same for architectures resolving dependencies on
- the parts. While in DF mode it is better to always handle
- just register parts, the SF mode is different due to lack
- of instructions to load just part of the register. It is
- better to maintain the whole registers in single format
- to avoid problems on using packed logical operations. */
- (eq_attr "alternative" "6")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
- (const_int 0))
- (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS")
+ (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
(const_int 0)))
(const_string "V4SF")
(const_string "SF"))
@@ -2389,11 +2362,11 @@
(const_string "SF")))])
(define_insn "*swapsf"
- [(set (match_operand:SF 0 "register_operand" "+f")
- (match_operand:SF 1 "register_operand" "+f"))
+ [(set (match_operand:SF 0 "fp_register_operand" "+f")
+ (match_operand:SF 1 "fp_register_operand" "+f"))
(set (match_dup 1)
(match_dup 0))]
- "reload_completed || !TARGET_SSE"
+ "reload_completed || TARGET_80387"
{
if (STACK_TOP_P (operands[0]))
return "fxch\t%1";
@@ -2416,24 +2389,26 @@
(define_insn "*pushdf_nointeger"
[(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
- (match_operand:DF 1 "general_no_elim_operand" "f#Y,Fo#fY,*r#fY,Y#f"))]
+ (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))]
"!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
{
/* This insn should be already split before reg-stack. */
- abort ();
+ gcc_unreachable ();
}
[(set_attr "type" "multi")
+ (set_attr "unit" "i387,*,*,*")
(set_attr "mode" "DF,SI,SI,DF")])
(define_insn "*pushdf_integer"
[(set (match_operand:DF 0 "push_operand" "=<,<,<")
- (match_operand:DF 1 "general_no_elim_operand" "f#rY,rFo#fY,Y#rf"))]
+ (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))]
"TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
{
/* This insn should be already split before reg-stack. */
- abort ();
+ gcc_unreachable ();
}
[(set_attr "type" "multi")
+ (set_attr "unit" "i387,*,*")
(set_attr "mode" "DF,SI,DF")])
;; %%% Kill this when call knows how to work this out.
@@ -2441,16 +2416,16 @@
[(set (match_operand:DF 0 "push_operand" "")
(match_operand:DF 1 "any_fp_register_operand" ""))]
"!TARGET_64BIT && reload_completed"
- [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8)))
- (set (mem:DF (reg:SI 7)) (match_dup 1))]
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (set (mem:DF (reg:SI SP_REG)) (match_dup 1))]
"")
(define_split
[(set (match_operand:DF 0 "push_operand" "")
(match_operand:DF 1 "any_fp_register_operand" ""))]
"TARGET_64BIT && reload_completed"
- [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8)))
- (set (mem:DF (reg:DI 7)) (match_dup 1))]
+ [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
+ (set (mem:DF (reg:DI SP_REG)) (match_dup 1))]
"")
(define_split
@@ -2465,8 +2440,10 @@
;; when optimizing for size.
(define_insn "*movdf_nointeger"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,m,f#Y,*r,o,Y#f,Y#f,Y#f,m")
- (match_operand:DF 1 "general_operand" "fm#Y,f#Y,G,*roF,F*r,C,Y#f,YHm#f,Y#f"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand"
+ "=f,m,f,*r ,o ,Y*x,Y*x,Y*x ,m ")
+ (match_operand:DF 1 "general_operand"
+ "fm,f,G,*roF,F*r,C ,Y*x,mY*x,Y*x"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
&& (reload_in_progress || reload_completed
@@ -2477,18 +2454,7 @@
switch (which_alternative)
{
case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- {
- if (REGNO (operands[0]) == FIRST_STACK_REG
- && TARGET_USE_FFREEP)
- return "ffreep\t%y0";
- return "fstp\t%y0";
- }
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
+ return output_387_reg_move (insn, operands);
case 1:
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
@@ -2512,36 +2478,49 @@
case MODE_TI:
return "pxor\t%0, %0";
default:
- abort ();
+ gcc_unreachable ();
}
case 6:
+ case 7:
+ case 8:
switch (get_attr_mode (insn))
{
case MODE_V4SF:
return "movaps\t{%1, %0|%0, %1}";
case MODE_V2DF:
return "movapd\t{%1, %0|%0, %1}";
+ case MODE_TI:
+ return "movdqa\t{%1, %0|%0, %1}";
+ case MODE_DI:
+ return "movq\t{%1, %0|%0, %1}";
case MODE_DF:
return "movsd\t{%1, %0|%0, %1}";
+ case MODE_V1DF:
+ return "movlpd\t{%1, %0|%0, %1}";
+ case MODE_V2SF:
+ return "movlps\t{%1, %0|%0, %1}";
default:
- abort ();
+ gcc_unreachable ();
}
- case 7:
- if (get_attr_mode (insn) == MODE_V2DF)
- return "movlpd\t{%1, %0|%0, %1}";
- else
- return "movsd\t{%1, %0|%0, %1}";
- case 8:
- return "movsd\t{%1, %0|%0, %1}";
default:
- abort();
+ gcc_unreachable ();
}
}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov")
+ [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
(set (attr "mode")
- (cond [(eq_attr "alternative" "3,4")
+ (cond [(eq_attr "alternative" "0,1,2")
+ (const_string "DF")
+ (eq_attr "alternative" "3,4")
(const_string "SI")
+
+ /* For SSE1, we have many fewer alternatives. */
+ (eq (symbol_ref "TARGET_SSE2") (const_int 0))
+ (cond [(eq_attr "alternative" "5,6")
+ (const_string "V4SF")
+ ]
+ (const_string "V2SF"))
+
/* xorps is one byte shorter. */
(eq_attr "alternative" "5")
(cond [(ne (symbol_ref "optimize_size")
@@ -2549,8 +2528,10 @@
(const_string "V4SF")
(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
(const_int 0))
- (const_string "TI")]
+ (const_string "TI")
+ ]
(const_string "V2DF"))
+
/* For architectures resolving dependencies on
whole SSE registers use APD move to break dependency
chains, otherwise use short move to avoid extra work.
@@ -2558,27 +2539,31 @@
movaps encodes one byte shorter. */
(eq_attr "alternative" "6")
(cond
- [(ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
- (const_int 0))
- (const_string "V2DF")]
+ [(ne (symbol_ref "optimize_size")
+ (const_int 0))
+ (const_string "V4SF")
+ (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
+ (const_int 0))
+ (const_string "V2DF")
+ ]
(const_string "DF"))
/* For architectures resolving dependencies on register
parts we may avoid extra work to zero out upper part
of register. */
(eq_attr "alternative" "7")
(if_then_else
- (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS")
+ (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
(const_int 0))
- (const_string "V2DF")
- (const_string "DF"))]
- (const_string "DF")))])
+ (const_string "V1DF")
+ (const_string "DF"))
+ ]
+ (const_string "DF")))])
(define_insn "*movdf_integer"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Yr,m,f#Yr,r#Yf,o,Y#rf,Y#rf,Y#rf,m")
- (match_operand:DF 1 "general_operand" "fm#Yr,f#Yr,G,roF#Yf,Fr#Yf,C,Y#rf,Ym#rf,Y#rf"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand"
+ "=f,m,f,r ,o ,Y*x,Y*x,Y*x,m ")
+ (match_operand:DF 1 "general_operand"
+ "fm,f,G,roF,Fr,C ,Y*x,m ,Y*x"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT)
&& (reload_in_progress || reload_completed
@@ -2589,18 +2574,7 @@
switch (which_alternative)
{
case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- {
- if (REGNO (operands[0]) == FIRST_STACK_REG
- && TARGET_USE_FFREEP)
- return "ffreep\t%y0";
- return "fstp\t%y0";
- }
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
+ return output_387_reg_move (insn, operands);
case 1:
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
@@ -2625,36 +2599,49 @@
case MODE_TI:
return "pxor\t%0, %0";
default:
- abort ();
+ gcc_unreachable ();
}
case 6:
+ case 7:
+ case 8:
switch (get_attr_mode (insn))
{
case MODE_V4SF:
return "movaps\t{%1, %0|%0, %1}";
case MODE_V2DF:
return "movapd\t{%1, %0|%0, %1}";
+ case MODE_TI:
+ return "movdqa\t{%1, %0|%0, %1}";
+ case MODE_DI:
+ return "movq\t{%1, %0|%0, %1}";
case MODE_DF:
return "movsd\t{%1, %0|%0, %1}";
+ case MODE_V1DF:
+ return "movlpd\t{%1, %0|%0, %1}";
+ case MODE_V2SF:
+ return "movlps\t{%1, %0|%0, %1}";
default:
- abort ();
+ gcc_unreachable ();
}
- case 7:
- if (get_attr_mode (insn) == MODE_V2DF)
- return "movlpd\t{%1, %0|%0, %1}";
- else
- return "movsd\t{%1, %0|%0, %1}";
- case 8:
- return "movsd\t{%1, %0|%0, %1}";
default:
- abort();
+ gcc_unreachable();
}
}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov")
+ [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
(set (attr "mode")
- (cond [(eq_attr "alternative" "3,4")
+ (cond [(eq_attr "alternative" "0,1,2")
+ (const_string "DF")
+ (eq_attr "alternative" "3,4")
(const_string "SI")
+
+ /* For SSE1, we have many fewer alternatives. */
+ (eq (symbol_ref "TARGET_SSE2") (const_int 0))
+ (cond [(eq_attr "alternative" "5,6")
+ (const_string "V4SF")
+ ]
+ (const_string "V2SF"))
+
/* xorps is one byte shorter. */
(eq_attr "alternative" "5")
(cond [(ne (symbol_ref "optimize_size")
@@ -2662,32 +2649,36 @@
(const_string "V4SF")
(ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
(const_int 0))
- (const_string "TI")]
+ (const_string "TI")
+ ]
(const_string "V2DF"))
+
/* For architectures resolving dependencies on
whole SSE registers use APD move to break dependency
- chains, otherwise use short move to avoid extra work.
+ chains, otherwise use short move to avoid extra work.
movaps encodes one byte shorter. */
(eq_attr "alternative" "6")
(cond
- [(ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
- (const_int 0))
- (const_string "V2DF")]
+ [(ne (symbol_ref "optimize_size")
+ (const_int 0))
+ (const_string "V4SF")
+ (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
+ (const_int 0))
+ (const_string "V2DF")
+ ]
(const_string "DF"))
/* For architectures resolving dependencies on register
parts we may avoid extra work to zero out upper part
of register. */
(eq_attr "alternative" "7")
(if_then_else
- (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS")
+ (ne (symbol_ref "TARGET_SSE_SPLIT_REGS")
(const_int 0))
- (const_string "V2DF")
- (const_string "DF"))]
- (const_string "DF")))])
+ (const_string "V1DF")
+ (const_string "DF"))
+ ]
+ (const_string "DF")))])
(define_split
[(set (match_operand:DF 0 "nonimmediate_operand" "")
@@ -2704,11 +2695,11 @@
"ix86_split_long_move (operands); DONE;")
(define_insn "*swapdf"
- [(set (match_operand:DF 0 "register_operand" "+f")
- (match_operand:DF 1 "register_operand" "+f"))
+ [(set (match_operand:DF 0 "fp_register_operand" "+f")
+ (match_operand:DF 1 "fp_register_operand" "+f"))
(set (match_dup 1)
(match_dup 0))]
- "reload_completed || !TARGET_SSE2"
+ "reload_completed || TARGET_80387"
{
if (STACK_TOP_P (operands[0]))
return "fxch\t%1";
@@ -2737,20 +2728,22 @@
"optimize_size"
{
/* This insn should be already split before reg-stack. */
- abort ();
+ gcc_unreachable ();
}
[(set_attr "type" "multi")
+ (set_attr "unit" "i387,*,*")
(set_attr "mode" "XF,SI,SI")])
(define_insn "*pushxf_integer"
[(set (match_operand:XF 0 "push_operand" "=<,<")
- (match_operand:XF 1 "general_no_elim_operand" "f#r,ro#f"))]
+ (match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
"!optimize_size"
{
/* This insn should be already split before reg-stack. */
- abort ();
+ gcc_unreachable ();
}
[(set_attr "type" "multi")
+ (set_attr "unit" "i387,*")
(set_attr "mode" "XF,SI")])
(define_split
@@ -2767,16 +2760,16 @@
[(set (match_operand:XF 0 "push_operand" "")
(match_operand:XF 1 "any_fp_register_operand" ""))]
"!TARGET_64BIT"
- [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2)))
- (set (mem:XF (reg:SI 7)) (match_dup 1))]
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
+ (set (mem:XF (reg:SI SP_REG)) (match_dup 1))]
"operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
(define_split
[(set (match_operand:XF 0 "push_operand" "")
(match_operand:XF 1 "any_fp_register_operand" ""))]
"TARGET_64BIT"
- [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2)))
- (set (mem:XF (reg:DI 7)) (match_dup 1))]
+ [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
+ (set (mem:XF (reg:DI SP_REG)) (match_dup 1))]
"operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
;; Do not use integer registers when optimizing for size
@@ -2792,18 +2785,7 @@
switch (which_alternative)
{
case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- {
- if (REGNO (operands[0]) == FIRST_STACK_REG
- && TARGET_USE_FFREEP)
- return "ffreep\t%y0";
- return "fstp\t%y0";
- }
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
+ return output_387_reg_move (insn, operands);
case 1:
/* There is no non-popping store to memory for XFmode. So if
@@ -2818,15 +2800,16 @@
case 3: case 4:
return "#";
+ default:
+ gcc_unreachable ();
}
- abort();
}
[(set_attr "type" "fmov,fmov,fmov,multi,multi")
(set_attr "mode" "XF,XF,XF,SI,SI")])
(define_insn "*movxf_integer"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
- (match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o")
+ (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))]
"!optimize_size
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& (reload_in_progress || reload_completed
@@ -2836,18 +2819,7 @@
switch (which_alternative)
{
case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- {
- if (REGNO (operands[0]) == FIRST_STACK_REG
- && TARGET_USE_FFREEP)
- return "ffreep\t%y0";
- return "fstp\t%y0";
- }
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
+ return output_387_reg_move (insn, operands);
case 1:
/* There is no non-popping store to memory for XFmode. So if
@@ -2862,8 +2834,10 @@
case 3: case 4:
return "#";
+
+ default:
+ gcc_unreachable ();
}
- abort();
}
[(set_attr "type" "fmov,fmov,fmov,multi,multi")
(set_attr "mode" "XF,XF,XF,SI,SI")])
@@ -2920,7 +2894,7 @@
(match_operand:XF 1 "register_operand" "+f"))
(set (match_dup 1)
(match_dup 0))]
- ""
+ "TARGET_80387"
{
if (STACK_TOP_P (operands[0]))
return "fxch\t%1";
@@ -2929,6 +2903,67 @@
}
[(set_attr "type" "fxch")
(set_attr "mode" "XF")])
+
+(define_expand "movtf"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (match_operand:TF 1 "nonimmediate_operand" ""))]
+ "TARGET_64BIT"
+{
+ ix86_expand_move (TFmode, operands);
+ DONE;
+})
+
+(define_insn "*movtf_internal"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm")
+ (match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))]
+ "TARGET_64BIT
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ return "#";
+ case 2:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "xorps\t%0, %0";
+ else
+ return "pxor\t%0, %0";
+ case 3:
+ case 4:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "movaps\t{%1, %0|%0, %1}";
+ else
+ return "movdqa\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "2,3")
+ (if_then_else
+ (ne (symbol_ref "optimize_size")
+ (const_int 0))
+ (const_string "V4SF")
+ (const_string "TI"))
+ (eq_attr "alternative" "4")
+ (if_then_else
+ (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
+ (const_int 0))
+ (ne (symbol_ref "optimize_size")
+ (const_int 0)))
+ (const_string "V4SF")
+ (const_string "TI"))]
+ (const_string "DI")))])
+
+(define_split
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (match_operand:TF 1 "general_operand" ""))]
+ "reload_completed && !SSE_REG_P (operands[0])
+ && !SSE_REG_P (operands[1])"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
;; Zero extension instructions
@@ -2948,7 +2983,7 @@
(define_insn "zero_extendhisi2_and"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:HI 1 "register_operand" "0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
"#"
[(set_attr "type" "alu1")
@@ -2957,10 +2992,10 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI (match_operand:HI 1 "register_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
[(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_insn "*zero_extendhisi2_movzwl"
@@ -2975,14 +3010,14 @@
[(parallel
[(set (match_operand:HI 0 "register_operand" "")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
(define_insn "*zero_extendqihi2_and"
[(set (match_operand:HI 0 "register_operand" "=r,?&q")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
"#"
[(set_attr "type" "alu1")
@@ -2991,25 +3026,26 @@
(define_insn "*zero_extendqihi2_movzbw_and"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
"#"
[(set_attr "type" "imovx,alu1")
(set_attr "mode" "HI")])
-(define_insn "*zero_extendqihi2_movzbw"
+; zero extend to SImode here to avoid partial register stalls
+(define_insn "*zero_extendqihi2_movzbl"
[(set (match_operand:HI 0 "register_operand" "=r")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
"(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
- "movz{bw|x}\t{%1, %0|%0, %1}"
+ "movz{bl|x}\t{%1, %k0|%k0, %k1}"
[(set_attr "type" "imovx")
- (set_attr "mode" "HI")])
+ (set_attr "mode" "SI")])
;; For the movzbw case strip only the clobber
(define_split
[(set (match_operand:HI 0 "register_operand" "")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
&& (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
@@ -3021,7 +3057,7 @@
(define_split
[(set (match_operand:HI 0 "register_operand" "")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ANY_QI_REG_P (operands[0])
&& (TARGET_ZERO_EXTEND_WITH_AND && !optimize_size)
@@ -3034,25 +3070,25 @@
(define_split
[(set (match_operand:HI 0 "register_operand" "")
(zero_extend:HI (match_operand:QI 1 "register_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& true_regnum (operands[0]) == true_regnum (operands[1])"
[(parallel [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_expand "zero_extendqisi2"
[(parallel
[(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
(define_insn "*zero_extendqisi2_and"
[(set (match_operand:SI 0 "register_operand" "=r,?&q")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_ZERO_EXTEND_WITH_AND && !optimize_size"
"#"
[(set_attr "type" "alu1")
@@ -3061,7 +3097,7 @@
(define_insn "*zero_extendqisi2_movzbw_and"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm,0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_ZERO_EXTEND_WITH_AND || optimize_size"
"#"
[(set_attr "type" "imovx,alu1")
@@ -3079,7 +3115,7 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& (!TARGET_ZERO_EXTEND_WITH_AND || optimize_size)
&& (!REG_P (operands[1]) || ANY_QI_REG_P (operands[1]))"
@@ -3091,7 +3127,7 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ANY_QI_REG_P (operands[0])
&& (ANY_QI_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)
@@ -3105,11 +3141,11 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI (match_operand:QI 1 "register_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& true_regnum (operands[0]) == true_regnum (operands[1])"
[(parallel [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
;; %%% Kill me once multi-word ops are sane.
@@ -3125,24 +3161,10 @@
")
(define_insn "zero_extendsidi2_32"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,!?y,!?Y")
- (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,m,m")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && !TARGET_INTER_UNIT_MOVES"
- "@
- #
- #
- #
- movd\t{%1, %0|%0, %1}
- movd\t{%1, %0|%0, %1}"
- [(set_attr "mode" "SI,SI,SI,DI,TI")
- (set_attr "type" "multi,multi,multi,mmxmov,ssemov")])
-
-(define_insn "*zero_extendsidi2_32_1"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,!?y,!?Y")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,?*y,?*Y")
(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,rm,rm")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_INTER_UNIT_MOVES"
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT"
"@
#
#
@@ -3153,21 +3175,9 @@
(set_attr "type" "multi,multi,multi,mmxmov,ssemov")])
(define_insn "zero_extendsidi2_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,!?y,!?Y")
- (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,m,m")))]
- "TARGET_64BIT && !TARGET_INTER_UNIT_MOVES"
- "@
- mov\t{%k1, %k0|%k0, %k1}
- #
- movd\t{%1, %0|%0, %1}
- movd\t{%1, %0|%0, %1}"
- [(set_attr "type" "imovx,imov,mmxmov,ssemov")
- (set_attr "mode" "SI,DI,DI,TI")])
-
-(define_insn "*zero_extendsidi2_rex64_1"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,!?y,!*?")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*y,?*Y")
(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,rm,rm")))]
- "TARGET_64BIT && TARGET_INTER_UNIT_MOVES"
+ "TARGET_64BIT"
"@
mov\t{%k1, %k0|%k0, %k1}
#
@@ -3186,7 +3196,7 @@
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && reload_completed
&& true_regnum (operands[0]) == true_regnum (operands[1])"
[(set (match_dup 4) (const_int 0))]
@@ -3195,7 +3205,7 @@
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(zero_extend:DI (match_operand:SI 1 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && reload_completed
&& !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])"
[(set (match_dup 3) (match_dup 1))
@@ -3203,31 +3213,27 @@
"split_di (&operands[0], 1, &operands[3], &operands[4]);")
(define_insn "zero_extendhidi2"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
"TARGET_64BIT"
- "@
- movz{wl|x}\t{%1, %k0|%k0, %1}
- movz{wq|x}\t{%1, %0|%0, %1}"
+ "movz{wl|x}\t{%1, %k0|%k0, %1}"
[(set_attr "type" "imovx")
- (set_attr "mode" "SI,DI")])
+ (set_attr "mode" "DI")])
(define_insn "zero_extendqidi2"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "Q,m")))]
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
"TARGET_64BIT"
- "@
- movz{bl|x}\t{%1, %k0|%k0, %1}
- movz{bq|x}\t{%1, %0|%0, %1}"
+ "movz{bl|x}\t{%1, %k0|%k0, %1}"
[(set_attr "type" "imovx")
- (set_attr "mode" "SI,DI")])
+ (set_attr "mode" "DI")])
;; Sign extension instructions
(define_expand "extendsidi2"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
- (clobber (reg:CC 17))
+ (clobber (reg:CC FLAGS_REG))
(clobber (match_scratch:SI 2 ""))])]
""
{
@@ -3241,7 +3247,7 @@
(define_insn "*extendsidi2_1"
[(set (match_operand:DI 0 "nonimmediate_operand" "=*A,r,?r,?*o")
(sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,r")))
- (clobber (reg:CC 17))
+ (clobber (reg:CC FLAGS_REG))
(clobber (match_scratch:SI 2 "=X,X,X,&r"))]
"!TARGET_64BIT"
"#")
@@ -3278,14 +3284,14 @@
(define_split
[(set (match_operand:DI 0 "memory_operand" "")
(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
- (clobber (reg:CC 17))
+ (clobber (reg:CC FLAGS_REG))
(clobber (match_operand:SI 2 "register_operand" ""))]
"(reload_completed
&& dead_or_set_p (insn, operands[1])
&& !reg_mentioned_p (operands[1], operands[0]))"
[(set (match_dup 3) (match_dup 1))
(parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(set (match_dup 4) (match_dup 1))]
"split_di (&operands[0], 1, &operands[3], &operands[4]);")
@@ -3293,7 +3299,7 @@
(define_split
[(set (match_operand:DI 0 "memory_operand" "")
(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
- (clobber (reg:CC 17))
+ (clobber (reg:CC FLAGS_REG))
(clobber (match_operand:SI 2 "register_operand" ""))]
"reload_completed"
[(const_int 0)]
@@ -3323,7 +3329,7 @@
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
- (clobber (reg:CC 17))
+ (clobber (reg:CC FLAGS_REG))
(clobber (match_scratch:SI 2 ""))]
"reload_completed"
[(const_int 0)]
@@ -3460,15 +3466,15 @@
[(set (match_operand:DF 0 "push_operand" "")
(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
"!TARGET_64BIT"
- [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8)))
- (set (mem:DF (reg:SI 7)) (float_extend:DF (match_dup 1)))])
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (set (mem:DF (reg:SI SP_REG)) (float_extend:DF (match_dup 1)))])
(define_split
[(set (match_operand:DF 0 "push_operand" "")
(float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
"TARGET_64BIT"
- [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8)))
- (set (mem:DF (reg:DI 7)) (float_extend:DF (match_dup 1)))])
+ [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
+ (set (mem:DF (reg:DI SP_REG)) (float_extend:DF (match_dup 1)))])
(define_insn "*dummy_extendsfxf2"
[(set (match_operand:XF 0 "push_operand" "=<")
@@ -3480,89 +3486,117 @@
[(set (match_operand:XF 0 "push_operand" "")
(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
""
- [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2)))
- (set (mem:XF (reg:SI 7)) (float_extend:XF (match_dup 1)))]
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
+ (set (mem:XF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
"operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
(define_split
[(set (match_operand:XF 0 "push_operand" "")
(float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
"TARGET_64BIT"
- [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2)))
- (set (mem:DF (reg:DI 7)) (float_extend:XF (match_dup 1)))]
+ [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
+ (set (mem:DF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
"operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
(define_split
[(set (match_operand:XF 0 "push_operand" "")
(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
""
- [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2)))
- (set (mem:DF (reg:SI 7)) (float_extend:XF (match_dup 1)))]
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 2)))
+ (set (mem:DF (reg:SI SP_REG)) (float_extend:XF (match_dup 1)))]
"operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
(define_split
[(set (match_operand:XF 0 "push_operand" "")
(float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
"TARGET_64BIT"
- [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2)))
- (set (mem:XF (reg:DI 7)) (float_extend:XF (match_dup 1)))]
+ [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (match_dup 2)))
+ (set (mem:XF (reg:DI SP_REG)) (float_extend:XF (match_dup 1)))]
"operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);")
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(float_extend:DF (match_operand:SF 1 "general_operand" "")))]
- "TARGET_80387 || TARGET_SSE2"
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
{
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
+ {
+ if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387)
+ && standard_80387_constant_p (operands[1]) > 0)
+ {
+ operands[1] = simplify_const_unary_operation
+ (FLOAT_EXTEND, DFmode, operands[1], SFmode);
+ emit_move_insn_1 (operands[0], operands[1]);
+ DONE;
+ }
+ operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
+ }
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
-(define_insn "*extendsfdf2_1"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,mf#Y,Y#f")
- (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm#Y,f#Y,mY#f")))]
- "(TARGET_80387 || TARGET_SSE2)
+(define_insn "*extendsfdf2_mixed"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))]
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
{
switch (which_alternative)
{
case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp\t%y0";
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
+ return output_387_reg_move (insn, operands);
case 1:
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
return "fstp%z0\t%y0";
-
else
return "fst%z0\t%y0";
+
case 2:
return "cvtss2sd\t{%1, %0|%0, %1}";
default:
- abort ();
+ gcc_unreachable ();
}
}
[(set_attr "type" "fmov,fmov,ssecvt")
(set_attr "mode" "SF,XF,DF")])
-(define_insn "*extendsfdf2_1_sse_only"
- [(set (match_operand:DF 0 "register_operand" "=Y")
+(define_insn "*extendsfdf2_sse"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y")
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "mY")))]
- "!TARGET_80387 && TARGET_SSE2
+ "TARGET_SSE2 && TARGET_SSE_MATH
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"cvtss2sd\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
(set_attr "mode" "DF")])
+(define_insn "*extendsfdf2_i387"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_80387
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return output_387_reg_move (insn, operands);
+
+ case 1:
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return "fstp%z0\t%y0";
+ else
+ return "fst%z0\t%y0";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "fmov")
+ (set_attr "mode" "SF,XF")])
+
(define_expand "extendsfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "")
(float_extend:XF (match_operand:SF 1 "general_operand" "")))]
@@ -3571,12 +3605,21 @@
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
+ {
+ if (standard_80387_constant_p (operands[1]) > 0)
+ {
+ operands[1] = simplify_const_unary_operation
+ (FLOAT_EXTEND, XFmode, operands[1], SFmode);
+ emit_move_insn_1 (operands[0], operands[1]);
+ DONE;
+ }
+ operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
+ }
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
-(define_insn "*extendsfxf2_1"
+(define_insn "*extendsfxf2_i387"
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
"TARGET_80387
@@ -3585,24 +3628,18 @@
switch (which_alternative)
{
case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp\t%y0";
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
+ return output_387_reg_move (insn, operands);
case 1:
/* There is no non-popping store to memory for XFmode. So if
we need one, follow the store with a load. */
- if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0\n\tfld%z0\t%y0";
- else
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
return "fstp%z0\t%y0";
+ else
+ return "fstp%z0\t%y0\n\tfld%z0\t%y0";
default:
- abort ();
+ gcc_unreachable ();
}
}
[(set_attr "type" "fmov")
@@ -3616,12 +3653,21 @@
/* ??? Needed for compress_float_constant since all fp constants
are LEGITIMATE_CONSTANT_P. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
+ {
+ if (standard_80387_constant_p (operands[1]) > 0)
+ {
+ operands[1] = simplify_const_unary_operation
+ (FLOAT_EXTEND, XFmode, operands[1], DFmode);
+ emit_move_insn_1 (operands[0], operands[1]);
+ DONE;
+ }
+ operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
+ }
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (DFmode, operands[1]);
})
-(define_insn "*extenddfxf2_1"
+(define_insn "*extenddfxf2_i387"
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
(float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
"TARGET_80387
@@ -3630,13 +3676,7 @@
switch (which_alternative)
{
case 0:
- if (REG_P (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp\t%y0";
- else if (STACK_TOP_P (operands[0]))
- return "fld%z1\t%y1";
- else
- return "fst\t%y0";
+ return output_387_reg_move (insn, operands);
case 1:
/* There is no non-popping store to memory for XFmode. So if
@@ -3647,7 +3687,7 @@
return "fstp%z0\t%y0";
default:
- abort ();
+ gcc_unreachable ();
}
}
[(set_attr "type" "fmov")
@@ -3659,49 +3699,40 @@
;; insn. So we pretend we can output to a reg in order to get better
;; register preferencing, but we really use a stack slot.
-(define_expand "truncdfsf2"
- [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (float_truncate:SF
- (match_operand:DF 1 "register_operand" "")))
- (clobber (match_dup 2))])]
- "TARGET_80387 || TARGET_SSE2"
- "
- if (TARGET_80387)
- operands[2] = assign_386_stack_local (SFmode, 0);
- else
- {
- emit_insn (gen_truncdfsf2_sse_only (operands[0], operands[1]));
- DONE;
- }
-")
+;; Conversion from DFmode to SFmode.
-(define_insn "*truncdfsf2_1"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf")
+(define_expand "truncdfsf2"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(float_truncate:SF
- (match_operand:DF 1 "register_operand" "f,f,f,f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
- "TARGET_80387 && !TARGET_SSE2"
+ (match_operand:DF 1 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
{
- switch (which_alternative)
+ if (MEM_P (operands[0]) && MEM_P (operands[1]))
+ operands[1] = force_reg (DFmode, operands[1]);
+
+ if (TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387)
+ ;
+ else if (flag_unsafe_math_optimizations)
+ ;
+ else
{
- case 0:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
- default:
- abort ();
+ rtx temp = assign_386_stack_local (SFmode, SLOT_TEMP);
+ emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
+ DONE;
}
-}
- [(set_attr "type" "fmov,multi,multi,multi")
- (set_attr "mode" "SF,SF,SF,SF")])
+})
-(define_insn "*truncdfsf2_1_sse"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=*!m#fxr,?f#xr,?r#fx,?x#fr,Y#fr")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "f#Y,f#Y,f#Y,f#Y,mY#f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m,X"))]
- "TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS"
+(define_expand "truncdfsf2_with_temp"
+ [(parallel [(set (match_operand:SF 0 "" "")
+ (float_truncate:SF (match_operand:DF 1 "" "")))
+ (clobber (match_operand:SF 2 "" ""))])]
+ "")
+
+(define_insn "*truncdfsf_fast_mixed"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,f,Y")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "f ,f,Ym")))]
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations"
{
switch (which_alternative)
{
@@ -3710,21 +3741,43 @@
return "fstp%z0\t%y0";
else
return "fst%z0\t%y0";
- case 4:
- return "#";
+ case 1:
+ return output_387_reg_move (insn, operands);
+ case 2:
+ return "cvtsd2ss\t{%1, %0|%0, %1}";
default:
- abort ();
+ gcc_unreachable ();
}
}
- [(set_attr "type" "fmov,multi,multi,multi,ssecvt")
- (set_attr "mode" "SF,SF,SF,SF,DF")])
+ [(set_attr "type" "fmov,fmov,ssecvt")
+ (set_attr "mode" "SF")])
+
+;; Yes, this one doesn't depend on flag_unsafe_math_optimizations,
+;; because nothing we do here is unsafe.
+(define_insn "*truncdfsf_fast_sse"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=Y")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "cvtsd2ss\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SF")])
+
+(define_insn "*truncdfsf_fast_i387"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=fm")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "f")))]
+ "TARGET_80387 && flag_unsafe_math_optimizations"
+ "* return output_387_reg_move (insn, operands);"
+ [(set_attr "type" "fmov")
+ (set_attr "mode" "SF")])
-(define_insn "*truncdfsf2_1_sse_nooverlap"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=*!m,?f#rx,?r#fx,?x#rf,&Y")
+(define_insn "*truncdfsf_mixed"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r,Y")
(float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "f#Y,f#Y,f#Y,f#Y,mY#f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m,X"))]
- "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS"
+ (match_operand:DF 1 "nonimmediate_operand" "f ,f ,Ym")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m ,X"))]
+ "TARGET_MIX_SSE_I387"
{
switch (which_alternative)
{
@@ -3733,68 +3786,49 @@
return "fstp%z0\t%y0";
else
return "fst%z0\t%y0";
- case 4:
- return "#";
- default:
- abort ();
- }
-}
- [(set_attr "type" "fmov,multi,multi,multi,ssecvt")
- (set_attr "mode" "SF,SF,SF,SF,DF")])
-
-(define_insn "*truncdfsf2_2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=Y,Y,!m")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "Y,mY,f#Y")))]
- "TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
case 1:
- return "cvtsd2ss\t{%1, %0|%0, %1}";
+ return "#";
case 2:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
+ return "cvtsd2ss\t{%1, %0|%0, %1}";
default:
- abort ();
+ gcc_unreachable ();
}
}
- [(set_attr "type" "ssecvt,ssecvt,fmov")
- (set_attr "athlon_decode" "vector,double,*")
- (set_attr "mode" "SF,SF,SF")])
+ [(set_attr "type" "fmov,multi,ssecvt")
+ (set_attr "unit" "*,i387,*")
+ (set_attr "mode" "SF")])
-(define_insn "*truncdfsf2_2_nooverlap"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=&Y,!m")
+(define_insn "*truncdfsf_i387"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r")
(float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "mY,f")))]
- "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ (match_operand:DF 1 "nonimmediate_operand" "f,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m"))]
+ "TARGET_80387"
{
switch (which_alternative)
{
case 0:
- return "#";
- case 1:
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
return "fstp%z0\t%y0";
else
return "fst%z0\t%y0";
+ case 1:
+ return "#";
default:
- abort ();
+ gcc_unreachable ();
}
}
- [(set_attr "type" "ssecvt,fmov")
- (set_attr "mode" "DF,SF")])
+ [(set_attr "type" "fmov,multi")
+ (set_attr "unit" "*,i387")
+ (set_attr "mode" "SF")])
-(define_insn "*truncdfsf2_3"
+(define_insn "*truncdfsf2_i387_1"
[(set (match_operand:SF 0 "memory_operand" "=m")
(float_truncate:SF
- (match_operand:DF 1 "register_operand" "f")))]
- "TARGET_80387"
+ (match_operand:DF 1 "register_operand" "f")))]
+ "TARGET_80387
+ && !(TARGET_SSE2 && TARGET_SSE_MATH)
+ && !TARGET_MIX_SSE_I387"
{
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
return "fstp%z0\t%y0";
@@ -3804,94 +3838,19 @@
[(set_attr "type" "fmov")
(set_attr "mode" "SF")])
-(define_insn "truncdfsf2_sse_only"
- [(set (match_operand:SF 0 "register_operand" "=Y,Y")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "Y,mY")))]
- "!TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS"
- "cvtsd2ss\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "athlon_decode" "vector,double")
- (set_attr "mode" "SF")])
-
-(define_insn "*truncdfsf2_sse_only_nooverlap"
- [(set (match_operand:SF 0 "register_operand" "=&Y")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "mY")))]
- "!TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS"
- "#"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "DF")])
-
-(define_split
- [(set (match_operand:SF 0 "memory_operand" "")
- (float_truncate:SF
- (match_operand:DF 1 "register_operand" "")))
- (clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387"
- [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
- "")
-
-; Avoid possible reformatting penalty on the destination by first
-; zeroing it out
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "")))
+ (match_operand:DF 1 "fp_register_operand" "")))
(clobber (match_operand 2 "" ""))]
- "TARGET_80387 && reload_completed
- && SSE_REG_P (operands[0])
- && !STACK_REG_P (operands[1])"
- [(const_int 0)]
-{
- rtx src, dest;
- if (!TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS)
- emit_insn (gen_truncdfsf2_sse_only (operands[0], operands[1]));
- else
- {
- dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
- src = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0);
- /* simplify_gen_subreg refuses to widen memory references. */
- if (GET_CODE (src) == SUBREG)
- alter_subreg (&src);
- if (reg_overlap_mentioned_p (operands[0], operands[1]))
- abort ();
- emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode)));
- emit_insn (gen_cvtsd2ss (dest, dest, src));
- }
- DONE;
-})
-
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "")))]
- "TARGET_80387 && reload_completed
- && SSE_REG_P (operands[0]) && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS"
- [(const_int 0)]
+ "reload_completed"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (match_dup 2))]
{
- rtx src, dest;
- dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
- src = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0);
- /* simplify_gen_subreg refuses to widen memory references. */
- if (GET_CODE (src) == SUBREG)
- alter_subreg (&src);
- if (reg_overlap_mentioned_p (operands[0], operands[1]))
- abort ();
- emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode)));
- emit_insn (gen_cvtsd2ss (dest, dest, src));
- DONE;
+ operands[1] = gen_rtx_REG (SFmode, true_regnum (operands[1]));
})
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (float_truncate:SF
- (match_operand:DF 1 "fp_register_operand" "")))
- (clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
- (set (match_dup 0) (match_dup 2))]
- "")
+;; Conversion from XFmode to SFmode.
(define_expand "truncxfsf2"
[(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
@@ -3899,30 +3858,64 @@
(match_operand:XF 1 "register_operand" "")))
(clobber (match_dup 2))])]
"TARGET_80387"
- "operands[2] = assign_386_stack_local (SFmode, 0);")
+{
+ if (flag_unsafe_math_optimizations)
+ {
+ rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode);
+ emit_insn (gen_truncxfsf2_i387_noop (reg, operands[1]));
+ if (reg != operands[0])
+ emit_move_insn (operands[0], reg);
+ DONE;
+ }
+ else
+ operands[2] = assign_386_stack_local (SFmode, SLOT_TEMP);
+})
-(define_insn "*truncxfsf2_1"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf")
+(define_insn "*truncxfsf2_mixed"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "f,f,f,f")))
(clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
- "TARGET_80387"
+ "TARGET_MIX_SSE_I387"
{
- switch (which_alternative)
- {
- case 0:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
- default:
- abort();
- }
+ gcc_assert (!which_alternative);
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return "fstp%z0\t%y0";
+ else
+ return "fst%z0\t%y0";
}
[(set_attr "type" "fmov,multi,multi,multi")
+ (set_attr "unit" "*,i387,i387,i387")
+ (set_attr "mode" "SF")])
+
+(define_insn "truncxfsf2_i387_noop"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
+ "TARGET_80387 && flag_unsafe_math_optimizations"
+{
+ return output_387_reg_move (insn, operands);
+}
+ [(set_attr "type" "fmov")
(set_attr "mode" "SF")])
-(define_insn "*truncxfsf2_2"
+(define_insn "*truncxfsf2_i387"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r")
+ (float_truncate:SF
+ (match_operand:XF 1 "register_operand" "f,f,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
+ "TARGET_80387"
+{
+ gcc_assert (!which_alternative);
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return "fstp%z0\t%y0";
+ else
+ return "fst%z0\t%y0";
+}
+ [(set_attr "type" "fmov,multi,multi")
+ (set_attr "unit" "*,i387,i387")
+ (set_attr "mode" "SF")])
+
+(define_insn "*truncxfsf2_i387_1"
[(set (match_operand:SF 0 "memory_operand" "=m")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "f")))]
@@ -3937,55 +3930,90 @@
(set_attr "mode" "SF")])
(define_split
- [(set (match_operand:SF 0 "memory_operand" "")
+ [(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387"
- [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
+ (set (match_dup 0) (match_dup 2))]
"")
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
+ [(set (match_operand:SF 0 "memory_operand" "")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
- (set (match_dup 0) (match_dup 2))]
+ "TARGET_80387"
+ [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
"")
+;; Conversion from XFmode to DFmode.
+
(define_expand "truncxfdf2"
[(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_dup 2))])]
"TARGET_80387"
- "operands[2] = assign_386_stack_local (DFmode, 0);")
+{
+ if (flag_unsafe_math_optimizations)
+ {
+ rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DFmode);
+ emit_insn (gen_truncxfdf2_i387_noop (reg, operands[1]));
+ if (reg != operands[0])
+ emit_move_insn (operands[0], reg);
+ DONE;
+ }
+ else
+ operands[2] = assign_386_stack_local (DFmode, SLOT_TEMP);
+})
-(define_insn "*truncxfdf2_1"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf")
+(define_insn "*truncxfdf2_mixed"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "f,f,f,f")))
(clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
- "TARGET_80387"
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387"
{
- switch (which_alternative)
- {
- case 0:
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
- default:
- abort();
- }
- abort ();
+ gcc_assert (!which_alternative);
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return "fstp%z0\t%y0";
+ else
+ return "fst%z0\t%y0";
}
[(set_attr "type" "fmov,multi,multi,multi")
+ (set_attr "unit" "*,i387,i387,i387")
(set_attr "mode" "DF")])
-(define_insn "*truncxfdf2_2"
+(define_insn "truncxfdf2_i387_noop"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
+ "TARGET_80387 && flag_unsafe_math_optimizations"
+{
+ return output_387_reg_move (insn, operands);
+}
+ [(set_attr "type" "fmov")
+ (set_attr "mode" "DF")])
+
+(define_insn "*truncxfdf2_i387"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r")
+ (float_truncate:DF
+ (match_operand:XF 1 "register_operand" "f,f,f")))
+ (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
+ "TARGET_80387"
+{
+ gcc_assert (!which_alternative);
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return "fstp%z0\t%y0";
+ else
+ return "fst%z0\t%y0";
+}
+ [(set_attr "type" "fmov,multi,multi")
+ (set_attr "unit" "*,i387,i387")
+ (set_attr "mode" "DF")])
+
+(define_insn "*truncxfdf2_i387_1"
[(set (match_operand:DF 0 "memory_operand" "=m")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "f")))]
@@ -4000,463 +4028,411 @@
(set_attr "mode" "DF")])
(define_split
- [(set (match_operand:DF 0 "memory_operand" "")
+ [(set (match_operand:DF 0 "register_operand" "")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_operand:DF 2 "memory_operand" ""))]
- "TARGET_80387"
- [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
+ (set (match_dup 0) (match_dup 2))]
"")
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "memory_operand" "")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_operand:DF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
- (set (match_dup 0) (match_dup 2))]
+ "TARGET_80387"
+ [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
"")
-
-;; %%% Break up all these bad boys.
-
;; Signed conversion to DImode.
(define_expand "fix_truncxfdi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (fix:DI (match_operand:XF 1 "register_operand" "")))]
+ [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (match_operand:XF 1 "register_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_80387"
- "")
-
-(define_expand "fix_truncdfdi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (fix:DI (match_operand:DF 1 "register_operand" "")))]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)"
{
- if (TARGET_64BIT && TARGET_SSE2)
+ if (TARGET_FISTTP)
{
- rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
- emit_insn (gen_fix_truncdfdi_sse (out, operands[1]));
- if (out != operands[0])
- emit_move_insn (operands[0], out);
+ emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
DONE;
}
})
-(define_expand "fix_truncsfdi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (fix:DI (match_operand:SF 1 "register_operand" "")))]
- "TARGET_80387 || (TARGET_SSE && TARGET_64BIT)"
+(define_expand "fix_trunc<mode>di2"
+ [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (match_operand:SSEMODEF 1 "register_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_80387 || (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))"
{
- if (TARGET_SSE && TARGET_64BIT)
+ if (TARGET_FISTTP
+ && !(TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
+ {
+ emit_insn (gen_fix_truncdi_fisttp_i387_1 (operands[0], operands[1]));
+ DONE;
+ }
+ if (TARGET_64BIT && SSE_FLOAT_MODE_P (<MODE>mode))
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
- emit_insn (gen_fix_truncsfdi_sse (out, operands[1]));
+ emit_insn (gen_fix_trunc<mode>di_sse (out, operands[1]));
if (out != operands[0])
emit_move_insn (operands[0], out);
DONE;
}
})
-;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
-;; of the machinery.
-(define_insn_and_split "*fix_truncdi_1"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
- (fix:DI (match_operand 1 "register_operand" "f,f")))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && !reload_completed && !reload_in_progress
- && (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
- "#"
- "&& 1"
- [(const_int 0)]
-{
- ix86_optimize_mode_switching = 1;
- operands[2] = assign_386_stack_local (HImode, 1);
- operands[3] = assign_386_stack_local (HImode, 2);
- if (memory_operand (operands[0], VOIDmode))
- emit_insn (gen_fix_truncdi_memory (operands[0], operands[1],
- operands[2], operands[3]));
- else
- {
- operands[4] = assign_386_stack_local (DImode, 0);
- emit_insn (gen_fix_truncdi_nomemory (operands[0], operands[1],
- operands[2], operands[3],
- operands[4]));
- }
- DONE;
-}
- [(set_attr "type" "fistp")
- (set_attr "mode" "DI")])
-
-(define_insn "fix_truncdi_nomemory"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
- (fix:DI (match_operand 1 "register_operand" "f,f")))
- (use (match_operand:HI 2 "memory_operand" "m,m"))
- (use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
- (clobber (match_scratch:DF 5 "=&1f,&1f"))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
- "#"
- [(set_attr "type" "fistp")
- (set_attr "mode" "DI")])
-
-(define_insn "fix_truncdi_memory"
- [(set (match_operand:DI 0 "memory_operand" "=m")
- (fix:DI (match_operand 1 "register_operand" "f")))
- (use (match_operand:HI 2 "memory_operand" "m"))
- (use (match_operand:HI 3 "memory_operand" "m"))
- (clobber (match_scratch:DF 4 "=&1f"))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)"
- "* operands[5] = operands[4]; return output_fix_trunc (insn, operands);"
- [(set_attr "type" "fistp")
- (set_attr "mode" "DI")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (fix:DI (match_operand 1 "register_operand" "")))
- (use (match_operand:HI 2 "memory_operand" ""))
- (use (match_operand:HI 3 "memory_operand" ""))
- (clobber (match_operand:DI 4 "memory_operand" ""))
- (clobber (match_scratch 5 ""))]
- "reload_completed"
- [(parallel [(set (match_dup 4) (fix:DI (match_dup 1)))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 5))])
- (set (match_dup 0) (match_dup 4))]
- "")
-
-(define_split
- [(set (match_operand:DI 0 "memory_operand" "")
- (fix:DI (match_operand 1 "register_operand" "")))
- (use (match_operand:HI 2 "memory_operand" ""))
- (use (match_operand:HI 3 "memory_operand" ""))
- (clobber (match_operand:DI 4 "memory_operand" ""))
- (clobber (match_scratch 5 ""))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (fix:DI (match_dup 1)))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 5))])]
- "")
-
-;; When SSE available, it is always faster to use it!
-(define_insn "fix_truncsfdi_sse"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
- "TARGET_64BIT && TARGET_SSE"
- "cvttss2si{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "SF")
- (set_attr "athlon_decode" "double,vector")])
-
-;; Avoid vector decoded form of the instruction.
-(define_peephole2
- [(match_scratch:SF 2 "x")
- (set (match_operand:DI 0 "register_operand" "")
- (fix:DI (match_operand:SF 1 "memory_operand" "")))]
- "TARGET_K8 && !optimize_size"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (fix:DI (match_dup 2)))]
- "")
-
-(define_insn "fix_truncdfdi_sse"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
- "TARGET_64BIT && TARGET_SSE2"
- "cvttsd2si{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt,sseicvt")
- (set_attr "mode" "DF")
- (set_attr "athlon_decode" "double,vector")])
-
-;; Avoid vector decoded form of the instruction.
-(define_peephole2
- [(match_scratch:DF 2 "Y")
- (set (match_operand:DI 0 "register_operand" "")
- (fix:DI (match_operand:DF 1 "memory_operand" "")))]
- "TARGET_K8 && !optimize_size"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (fix:DI (match_dup 2)))]
- "")
-
;; Signed conversion to SImode.
(define_expand "fix_truncxfsi2"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (fix:SI (match_operand:XF 1 "register_operand" "")))]
+ [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (match_operand:XF 1 "register_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_80387"
- "")
-
-(define_expand "fix_truncdfsi2"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (fix:SI (match_operand:DF 1 "register_operand" "")))]
- "TARGET_80387 || TARGET_SSE2"
{
- if (TARGET_SSE2)
+ if (TARGET_FISTTP)
{
- rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
- emit_insn (gen_fix_truncdfsi_sse (out, operands[1]));
- if (out != operands[0])
- emit_move_insn (operands[0], out);
+ emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
DONE;
}
})
-(define_expand "fix_truncsfsi2"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (fix:SI (match_operand:SF 1 "register_operand" "")))]
- "TARGET_80387 || TARGET_SSE"
+(define_expand "fix_trunc<mode>si2"
+ [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (match_operand:SSEMODEF 1 "register_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_80387 || SSE_FLOAT_MODE_P (<MODE>mode)"
{
- if (TARGET_SSE)
+ if (TARGET_FISTTP
+ && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))
+ {
+ emit_insn (gen_fix_truncsi_fisttp_i387_1 (operands[0], operands[1]));
+ DONE;
+ }
+ if (SSE_FLOAT_MODE_P (<MODE>mode))
{
rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SImode);
- emit_insn (gen_fix_truncsfsi_sse (out, operands[1]));
+ emit_insn (gen_fix_trunc<mode>si_sse (out, operands[1]));
if (out != operands[0])
emit_move_insn (operands[0], out);
DONE;
}
})
-;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
-;; of the machinery.
-(define_insn_and_split "*fix_truncsi_1"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r")
- (fix:SI (match_operand 1 "register_operand" "f,f")))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && !reload_completed && !reload_in_progress
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
- "#"
- "&& 1"
- [(const_int 0)]
+;; Signed conversion to HImode.
+
+(define_expand "fix_trunc<mode>hi2"
+ [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
+ (fix:HI (match_operand:X87MODEF 1 "register_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_80387
+ && !(SSE_FLOAT_MODE_P (<MODE>mode) && (!TARGET_FISTTP || TARGET_SSE_MATH))"
{
- ix86_optimize_mode_switching = 1;
- operands[2] = assign_386_stack_local (HImode, 1);
- operands[3] = assign_386_stack_local (HImode, 2);
- if (memory_operand (operands[0], VOIDmode))
- emit_insn (gen_fix_truncsi_memory (operands[0], operands[1],
- operands[2], operands[3]));
- else
- {
- operands[4] = assign_386_stack_local (SImode, 0);
- emit_insn (gen_fix_truncsi_nomemory (operands[0], operands[1],
- operands[2], operands[3],
- operands[4]));
- }
- DONE;
-}
- [(set_attr "type" "fistp")
- (set_attr "mode" "SI")])
+ if (TARGET_FISTTP)
+ {
+ emit_insn (gen_fix_trunchi_fisttp_i387_1 (operands[0], operands[1]));
+ DONE;
+ }
+})
-(define_insn "fix_truncsi_nomemory"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r")
- (fix:SI (match_operand 1 "register_operand" "f,f")))
- (use (match_operand:HI 2 "memory_operand" "m,m"))
- (use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:SI 4 "memory_operand" "=m,m"))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
- "#"
- [(set_attr "type" "fistp")
- (set_attr "mode" "SI")])
+;; When SSE is available, it is always faster to use it!
+(define_insn "fix_truncsfdi_sse"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
+ "TARGET_64BIT && TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
+ "cvttss2si{q}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "SF")
+ (set_attr "athlon_decode" "double,vector")])
-(define_insn "fix_truncsi_memory"
- [(set (match_operand:SI 0 "memory_operand" "=m")
- (fix:SI (match_operand 1 "register_operand" "f")))
- (use (match_operand:HI 2 "memory_operand" "m"))
- (use (match_operand:HI 3 "memory_operand" "m"))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
- "* return output_fix_trunc (insn, operands);"
- [(set_attr "type" "fistp")
- (set_attr "mode" "SI")])
+(define_insn "fix_truncdfdi_sse"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
+ "TARGET_64BIT && TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
+ "cvttsd2si{q}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "DF")
+ (set_attr "athlon_decode" "double,vector")])
-;; When SSE available, it is always faster to use it!
(define_insn "fix_truncsfsi_sse"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))]
- "TARGET_SSE"
+ "TARGET_SSE && (!TARGET_FISTTP || TARGET_SSE_MATH)"
"cvttss2si\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,vector")])
-;; Avoid vector decoded form of the instruction.
-(define_peephole2
- [(match_scratch:SF 2 "x")
- (set (match_operand:SI 0 "register_operand" "")
- (fix:SI (match_operand:SF 1 "memory_operand" "")))]
- "TARGET_K8 && !optimize_size"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (fix:SI (match_dup 2)))]
- "")
-
(define_insn "fix_truncdfsi_sse"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))]
- "TARGET_SSE2"
+ "TARGET_SSE2 && (!TARGET_FISTTP || TARGET_SSE_MATH)"
"cvttsd2si\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,vector")])
-;; Avoid vector decoded form of the instruction.
+;; Avoid vector decoded forms of the instruction.
(define_peephole2
[(match_scratch:DF 2 "Y")
- (set (match_operand:SI 0 "register_operand" "")
- (fix:SI (match_operand:DF 1 "memory_operand" "")))]
- "TARGET_K8 && !optimize_size"
+ (set (match_operand:SSEMODEI24 0 "register_operand" "")
+ (fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))]
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
[(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (fix:SI (match_dup 2)))]
+ (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
"")
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (fix:SI (match_operand 1 "register_operand" "")))
- (use (match_operand:HI 2 "memory_operand" ""))
- (use (match_operand:HI 3 "memory_operand" ""))
- (clobber (match_operand:SI 4 "memory_operand" ""))]
- "reload_completed"
- [(parallel [(set (match_dup 4) (fix:SI (match_dup 1)))
- (use (match_dup 2))
- (use (match_dup 3))])
- (set (match_dup 0) (match_dup 4))]
- "")
-
-(define_split
- [(set (match_operand:SI 0 "memory_operand" "")
- (fix:SI (match_operand 1 "register_operand" "")))
- (use (match_operand:HI 2 "memory_operand" ""))
- (use (match_operand:HI 3 "memory_operand" ""))
- (clobber (match_operand:SI 4 "memory_operand" ""))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (fix:SI (match_dup 1)))
- (use (match_dup 2))
- (use (match_dup 3))])]
+(define_peephole2
+ [(match_scratch:SF 2 "x")
+ (set (match_operand:SSEMODEI24 0 "register_operand" "")
+ (fix:SSEMODEI24 (match_operand:SF 1 "memory_operand" "")))]
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))]
"")
-;; Signed conversion to HImode.
-
-(define_expand "fix_truncxfhi2"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (fix:HI (match_operand:XF 1 "register_operand" "")))]
- "TARGET_80387"
- "")
+(define_insn_and_split "fix_trunc<mode>_fisttp_i387_1"
+ [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
+ (fix:X87MODEI (match_operand 1 "register_operand" "f,f")))]
+ "TARGET_FISTTP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && (TARGET_64BIT || <MODE>mode != DImode))
+ && TARGET_SSE_MATH)
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ if (memory_operand (operands[0], VOIDmode))
+ emit_insn (gen_fix_trunc<mode>_i387_fisttp (operands[0], operands[1]));
+ else
+ {
+ operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
+ emit_insn (gen_fix_trunc<mode>_i387_fisttp_with_temp (operands[0],
+ operands[1],
+ operands[2]));
+ }
+ DONE;
+}
+ [(set_attr "type" "fisttp")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fix_trunc<mode>_i387_fisttp"
+ [(set (match_operand:X87MODEI 0 "memory_operand" "=m")
+ (fix:X87MODEI (match_operand 1 "register_operand" "f")))
+ (clobber (match_scratch:XF 2 "=&1f"))]
+ "TARGET_FISTTP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && (TARGET_64BIT || <MODE>mode != DImode))
+ && TARGET_SSE_MATH)"
+ "* return output_fix_trunc (insn, operands, 1);"
+ [(set_attr "type" "fisttp")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fix_trunc<mode>_i387_fisttp_with_temp"
+ [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
+ (fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
+ (clobber (match_operand:X87MODEI 2 "memory_operand" "=m,m"))
+ (clobber (match_scratch:XF 3 "=&1f,&1f"))]
+ "TARGET_FISTTP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !((SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && (TARGET_64BIT || <MODE>mode != DImode))
+ && TARGET_SSE_MATH)"
+ "#"
+ [(set_attr "type" "fisttp")
+ (set_attr "mode" "<MODE>")])
-(define_expand "fix_truncdfhi2"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (fix:HI (match_operand:DF 1 "register_operand" "")))]
- "TARGET_80387 && !TARGET_SSE2"
+(define_split
+ [(set (match_operand:X87MODEI 0 "register_operand" "")
+ (fix:X87MODEI (match_operand 1 "register_operand" "")))
+ (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
+ (clobber (match_scratch 3 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 2) (fix:X87MODEI (match_dup 1)))
+ (clobber (match_dup 3))])
+ (set (match_dup 0) (match_dup 2))]
"")
-(define_expand "fix_truncsfhi2"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (fix:HI (match_operand:SF 1 "register_operand" "")))]
- "TARGET_80387 && !TARGET_SSE"
+(define_split
+ [(set (match_operand:X87MODEI 0 "memory_operand" "")
+ (fix:X87MODEI (match_operand 1 "register_operand" "")))
+ (clobber (match_operand:X87MODEI 2 "memory_operand" ""))
+ (clobber (match_scratch 3 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (fix:X87MODEI (match_dup 1)))
+ (clobber (match_dup 3))])]
"")
;; See the comments in i386.h near OPTIMIZE_MODE_SWITCHING for the description
-;; of the machinery.
-(define_insn_and_split "*fix_trunchi_1"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=m,?r")
- (fix:HI (match_operand 1 "register_operand" "f,f")))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && !reload_completed && !reload_in_progress
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
+;; of the machinery. Please note the clobber of FLAGS_REG. In i387 control
+;; word calculation (inserted by LCM in mode switching pass) a FLAGS_REG
+;; clobbering insns can be used. Look at emit_i387_cw_initialization ()
+;; function in i386.c.
+(define_insn_and_split "*fix_trunc<mode>_i387_1"
+ [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
+ (fix:X87MODEI (match_operand 1 "register_operand" "f,f")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_80387 && !TARGET_FISTTP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !(SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
+ && (TARGET_64BIT || <MODE>mode != DImode))
+ && !(reload_completed || reload_in_progress)"
"#"
- ""
+ "&& 1"
[(const_int 0)]
{
- ix86_optimize_mode_switching = 1;
- operands[2] = assign_386_stack_local (HImode, 1);
- operands[3] = assign_386_stack_local (HImode, 2);
+ ix86_optimize_mode_switching[I387_TRUNC] = 1;
+
+ operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+ operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
if (memory_operand (operands[0], VOIDmode))
- emit_insn (gen_fix_trunchi_memory (operands[0], operands[1],
- operands[2], operands[3]));
+ emit_insn (gen_fix_trunc<mode>_i387 (operands[0], operands[1],
+ operands[2], operands[3]));
else
{
- operands[4] = assign_386_stack_local (HImode, 0);
- emit_insn (gen_fix_trunchi_nomemory (operands[0], operands[1],
- operands[2], operands[3],
- operands[4]));
+ operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
+ emit_insn (gen_fix_trunc<mode>_i387_with_temp (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4]));
}
DONE;
}
[(set_attr "type" "fistp")
- (set_attr "mode" "HI")])
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "<MODE>")])
-(define_insn "fix_trunchi_nomemory"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=m,?r")
- (fix:HI (match_operand 1 "register_operand" "f,f")))
+(define_insn "fix_truncdi_i387"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (fix:DI (match_operand 1 "register_operand" "f")))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))
+ (clobber (match_scratch:XF 4 "=&1f"))]
+ "TARGET_80387 && !TARGET_FISTTP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "DI")])
+
+(define_insn "fix_truncdi_i387_with_temp"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
+ (fix:DI (match_operand 1 "register_operand" "f,f")))
(use (match_operand:HI 2 "memory_operand" "m,m"))
(use (match_operand:HI 3 "memory_operand" "m,m"))
- (clobber (match_operand:HI 4 "memory_operand" "=m,m"))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
+ (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
+ (clobber (match_scratch:XF 5 "=&1f,&1f"))]
+ "TARGET_80387 && !TARGET_FISTTP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !(TARGET_64BIT && SSE_FLOAT_MODE_P (GET_MODE (operands[1])))"
"#"
[(set_attr "type" "fistp")
- (set_attr "mode" "HI")])
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "DI")])
-(define_insn "fix_trunchi_memory"
- [(set (match_operand:HI 0 "memory_operand" "=m")
- (fix:HI (match_operand 1 "register_operand" "f")))
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (fix:DI (match_operand 1 "register_operand" "")))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:DI 4 "memory_operand" ""))
+ (clobber (match_scratch 5 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 4) (fix:DI (match_dup 1)))
+ (use (match_dup 2))
+ (use (match_dup 3))
+ (clobber (match_dup 5))])
+ (set (match_dup 0) (match_dup 4))]
+ "")
+
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (fix:DI (match_operand 1 "register_operand" "")))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:DI 4 "memory_operand" ""))
+ (clobber (match_scratch 5 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (fix:DI (match_dup 1)))
+ (use (match_dup 2))
+ (use (match_dup 3))
+ (clobber (match_dup 5))])]
+ "")
+
+(define_insn "fix_trunc<mode>_i387"
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
+ (fix:X87MODEI12 (match_operand 1 "register_operand" "f")))
(use (match_operand:HI 2 "memory_operand" "m"))
(use (match_operand:HI 3 "memory_operand" "m"))]
- "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "TARGET_80387 && !TARGET_FISTTP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
- "* return output_fix_trunc (insn, operands);"
+ "* return output_fix_trunc (insn, operands, 0);"
[(set_attr "type" "fistp")
- (set_attr "mode" "HI")])
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fix_trunc<mode>_i387_with_temp"
+ [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
+ (fix:X87MODEI12 (match_operand 1 "register_operand" "f,f")))
+ (use (match_operand:HI 2 "memory_operand" "m,m"))
+ (use (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
+ "TARGET_80387 && !TARGET_FISTTP
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))"
+ "#"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "<MODE>")])
(define_split
- [(set (match_operand:HI 0 "memory_operand" "")
- (fix:HI (match_operand 1 "register_operand" "")))
+ [(set (match_operand:X87MODEI12 0 "register_operand" "")
+ (fix:X87MODEI12 (match_operand 1 "register_operand" "")))
(use (match_operand:HI 2 "memory_operand" ""))
(use (match_operand:HI 3 "memory_operand" ""))
- (clobber (match_operand:HI 4 "memory_operand" ""))]
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
"reload_completed"
- [(parallel [(set (match_dup 0) (fix:HI (match_dup 1)))
+ [(parallel [(set (match_dup 4) (fix:X87MODEI12 (match_dup 1)))
(use (match_dup 2))
- (use (match_dup 3))])]
+ (use (match_dup 3))])
+ (set (match_dup 0) (match_dup 4))]
"")
(define_split
- [(set (match_operand:HI 0 "register_operand" "")
- (fix:HI (match_operand 1 "register_operand" "")))
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "")
+ (fix:X87MODEI12 (match_operand 1 "register_operand" "")))
(use (match_operand:HI 2 "memory_operand" ""))
(use (match_operand:HI 3 "memory_operand" ""))
- (clobber (match_operand:HI 4 "memory_operand" ""))]
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
"reload_completed"
- [(parallel [(set (match_dup 4) (fix:HI (match_dup 1)))
+ [(parallel [(set (match_dup 0) (fix:X87MODEI12 (match_dup 1)))
(use (match_dup 2))
- (use (match_dup 3))
- (clobber (match_dup 4))])
- (set (match_dup 0) (match_dup 4))]
+ (use (match_dup 3))])]
"")
-;; %% Not used yet.
(define_insn "x86_fnstcw_1"
[(set (match_operand:HI 0 "memory_operand" "=m")
- (unspec:HI [(reg:HI 18)] UNSPEC_FSTCW))]
+ (unspec:HI [(reg:HI FPSR_REG)] UNSPEC_FSTCW))]
"TARGET_80387"
"fnstcw\t%0"
[(set_attr "length" "2")
(set_attr "mode" "HI")
- (set_attr "unit" "i387")
- (set_attr "ppro_uops" "few")])
+ (set_attr "unit" "i387")])
(define_insn "x86_fldcw_1"
- [(set (reg:HI 18)
+ [(set (reg:HI FPSR_REG)
(unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
"TARGET_80387"
"fldcw\t%0"
[(set_attr "length" "2")
(set_attr "mode" "HI")
(set_attr "unit" "i387")
- (set_attr "athlon_decode" "vector")
- (set_attr "ppro_uops" "few")])
+ (set_attr "athlon_decode" "vector")])
;; Conversion between fixed point and floating point.
@@ -4466,9 +4442,9 @@
(define_expand "floathisf2"
[(set (match_operand:SF 0 "register_operand" "")
(float:SF (match_operand:HI 1 "nonimmediate_operand" "")))]
- "TARGET_SSE || TARGET_80387"
+ "TARGET_80387 || TARGET_SSE_MATH"
{
- if (TARGET_SSE && TARGET_SSE_MATH)
+ if (TARGET_SSE_MATH)
{
emit_insn (gen_floatsisf2 (operands[0],
convert_to_mode (SImode, operands[1], 0)));
@@ -4476,27 +4452,28 @@
}
})
-(define_insn "*floathisf2_1"
+(define_insn "*floathisf2_i387"
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (float:SF (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387 && (!TARGET_SSE || !TARGET_SSE_MATH)"
+ (float:SF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
+ "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
"@
fild%z1\t%1
#"
[(set_attr "type" "fmov,multi")
(set_attr "mode" "SF")
+ (set_attr "unit" "*,i387")
(set_attr "fp_int_src" "true")])
(define_expand "floatsisf2"
[(set (match_operand:SF 0 "register_operand" "")
(float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_SSE || TARGET_80387"
+ "TARGET_80387 || TARGET_SSE_MATH"
"")
-(define_insn "*floatsisf2_i387"
- [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f")
+(define_insn "*floatsisf2_mixed"
+ [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
- "TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)"
+ "TARGET_MIX_SSE_I387"
"@
fild%z1\t%1
#
@@ -4504,56 +4481,42 @@
cvtsi2ss\t{%1, %0|%0, %1}"
[(set_attr "type" "fmov,multi,sseicvt,sseicvt")
(set_attr "mode" "SF")
+ (set_attr "unit" "*,i387,*,*")
(set_attr "athlon_decode" "*,*,vector,double")
(set_attr "fp_int_src" "true")])
(define_insn "*floatsisf2_sse"
[(set (match_operand:SF 0 "register_operand" "=x,x")
(float:SF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
- "TARGET_SSE"
+ "TARGET_SSE_MATH"
"cvtsi2ss\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "SF")
(set_attr "athlon_decode" "vector,double")
(set_attr "fp_int_src" "true")])
-; Avoid possible reformatting penalty on the destination by first
-; zeroing it out
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 && reload_completed && TARGET_SSE_PARTIAL_REGS
- && SSE_REG_P (operands[0])"
- [(const_int 0)]
-{
- rtx dest;
- dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
- emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode)));
- emit_insn (gen_cvtsi2ss (dest, dest, operands[1]));
- DONE;
-})
-
-(define_expand "floatdisf2"
- [(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "(TARGET_64BIT && TARGET_SSE) || TARGET_80387"
- "")
-
-(define_insn "*floatdisf2_i387_only"
- [(set (match_operand:SF 0 "register_operand" "=f,?f")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387 && (!TARGET_SSE || !TARGET_64BIT || TARGET_MIX_SSE_I387)"
+(define_insn "*floatsisf2_i387"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
+ "TARGET_80387"
"@
fild%z1\t%1
#"
[(set_attr "type" "fmov,multi")
(set_attr "mode" "SF")
+ (set_attr "unit" "*,i387")
(set_attr "fp_int_src" "true")])
-(define_insn "*floatdisf2_i387"
- [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f")
+(define_expand "floatdisf2"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)"
+ "")
+
+(define_insn "*floatdisf2_mixed"
+ [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
- "TARGET_64BIT && TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)"
+ "TARGET_64BIT && TARGET_MIX_SSE_I387"
"@
fild%z1\t%1
#
@@ -4561,41 +4524,38 @@
cvtsi2ss{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "fmov,multi,sseicvt,sseicvt")
(set_attr "mode" "SF")
+ (set_attr "unit" "*,i387,*,*")
(set_attr "athlon_decode" "*,*,vector,double")
(set_attr "fp_int_src" "true")])
(define_insn "*floatdisf2_sse"
[(set (match_operand:SF 0 "register_operand" "=x,x")
(float:SF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
- "TARGET_64BIT && TARGET_SSE"
+ "TARGET_64BIT && TARGET_SSE_MATH"
"cvtsi2ss{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "SF")
(set_attr "athlon_decode" "vector,double")
(set_attr "fp_int_src" "true")])
-; Avoid possible reformatting penalty on the destination by first
-; zeroing it out
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 && reload_completed && TARGET_SSE_PARTIAL_REGS
- && SSE_REG_P (operands[0])"
- [(const_int 0)]
-{
- rtx dest;
- dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
- emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode)));
- emit_insn (gen_cvtsi2ssq (dest, dest, operands[1]));
- DONE;
-})
+(define_insn "*floatdisf2_i387"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
+ "TARGET_80387"
+ "@
+ fild%z1\t%1
+ #"
+ [(set_attr "type" "fmov,multi")
+ (set_attr "mode" "SF")
+ (set_attr "unit" "*,i387")
+ (set_attr "fp_int_src" "true")])
(define_expand "floathidf2"
[(set (match_operand:DF 0 "register_operand" "")
(float:DF (match_operand:HI 1 "nonimmediate_operand" "")))]
- "TARGET_SSE2 || TARGET_80387"
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
{
- if (TARGET_SSE && TARGET_SSE_MATH)
+ if (TARGET_SSE2 && TARGET_SSE_MATH)
{
emit_insn (gen_floatsidf2 (operands[0],
convert_to_mode (SImode, operands[1], 0)));
@@ -4603,27 +4563,28 @@
}
})
-(define_insn "*floathidf2_1"
+(define_insn "*floathidf2_i387"
[(set (match_operand:DF 0 "register_operand" "=f,f")
- (float:DF (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH)"
+ (float:DF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
+ "TARGET_80387 && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
"@
fild%z1\t%1
#"
[(set_attr "type" "fmov,multi")
(set_attr "mode" "DF")
+ (set_attr "unit" "*,i387")
(set_attr "fp_int_src" "true")])
(define_expand "floatsidf2"
[(set (match_operand:DF 0 "register_operand" "")
(float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 || TARGET_SSE2"
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
"")
-(define_insn "*floatsidf2_i387"
- [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f")
+(define_insn "*floatsidf2_mixed"
+ [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))]
- "TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)"
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387"
"@
fild%z1\t%1
#
@@ -4631,40 +4592,42 @@
cvtsi2sd\t{%1, %0|%0, %1}"
[(set_attr "type" "fmov,multi,sseicvt,sseicvt")
(set_attr "mode" "DF")
+ (set_attr "unit" "*,i387,*,*")
(set_attr "athlon_decode" "*,*,double,direct")
(set_attr "fp_int_src" "true")])
(define_insn "*floatsidf2_sse"
[(set (match_operand:DF 0 "register_operand" "=Y,Y")
(float:DF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))]
- "TARGET_SSE2"
+ "TARGET_SSE2 && TARGET_SSE_MATH"
"cvtsi2sd\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,direct")
(set_attr "fp_int_src" "true")])
-(define_expand "floatdidf2"
- [(set (match_operand:DF 0 "register_operand" "")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "(TARGET_64BIT && TARGET_SSE2) || TARGET_80387"
- "")
-
-(define_insn "*floatdidf2_i387_only"
- [(set (match_operand:DF 0 "register_operand" "=f,?f")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
- "TARGET_80387 && (!TARGET_SSE2 || !TARGET_64BIT)"
+(define_insn "*floatsidf2_i387"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
+ "TARGET_80387"
"@
fild%z1\t%1
#"
[(set_attr "type" "fmov,multi")
(set_attr "mode" "DF")
+ (set_attr "unit" "*,i387")
(set_attr "fp_int_src" "true")])
-(define_insn "*floatdidf2_i387"
- [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f")
+(define_expand "floatdidf2"
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH)"
+ "")
+
+(define_insn "*floatdidf2_mixed"
+ [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y")
(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))]
- "TARGET_64BIT && TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)"
+ "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
"@
fild%z1\t%1
#
@@ -4672,57 +4635,75 @@
cvtsi2sd{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "fmov,multi,sseicvt,sseicvt")
(set_attr "mode" "DF")
+ (set_attr "unit" "*,i387,*,*")
(set_attr "athlon_decode" "*,*,double,direct")
(set_attr "fp_int_src" "true")])
(define_insn "*floatdidf2_sse"
[(set (match_operand:DF 0 "register_operand" "=Y,Y")
(float:DF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))]
- "TARGET_SSE2"
+ "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
"cvtsi2sd{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,direct")
(set_attr "fp_int_src" "true")])
+(define_insn "*floatdidf2_i387"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
+ "TARGET_80387"
+ "@
+ fild%z1\t%1
+ #"
+ [(set_attr "type" "fmov,multi")
+ (set_attr "mode" "DF")
+ (set_attr "unit" "*,i387")
+ (set_attr "fp_int_src" "true")])
+
(define_insn "floathixf2"
[(set (match_operand:XF 0 "register_operand" "=f,f")
- (float:XF (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
+ (float:XF (match_operand:HI 1 "nonimmediate_operand" "m,?r")))]
"TARGET_80387"
"@
fild%z1\t%1
#"
[(set_attr "type" "fmov,multi")
(set_attr "mode" "XF")
+ (set_attr "unit" "*,i387")
(set_attr "fp_int_src" "true")])
(define_insn "floatsixf2"
[(set (match_operand:XF 0 "register_operand" "=f,f")
- (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,r")))]
+ (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
"TARGET_80387"
"@
fild%z1\t%1
#"
[(set_attr "type" "fmov,multi")
(set_attr "mode" "XF")
+ (set_attr "unit" "*,i387")
(set_attr "fp_int_src" "true")])
(define_insn "floatdixf2"
[(set (match_operand:XF 0 "register_operand" "=f,f")
- (float:XF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
+ (float:XF (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
"TARGET_80387"
"@
fild%z1\t%1
#"
[(set_attr "type" "fmov,multi")
(set_attr "mode" "XF")
+ (set_attr "unit" "*,i387")
(set_attr "fp_int_src" "true")])
;; %%% Kill these when reload knows how to do it.
(define_split
[(set (match_operand 0 "fp_register_operand" "")
(float (match_operand 1 "register_operand" "")))]
- "reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))"
+ "reload_completed
+ && TARGET_80387
+ && FLOAT_MODE_P (GET_MODE (operands[0]))"
[(const_int 0)]
{
operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
@@ -4735,187 +4716,61 @@
(define_expand "floatunssisf2"
[(use (match_operand:SF 0 "register_operand" ""))
(use (match_operand:SI 1 "register_operand" ""))]
- "TARGET_SSE && TARGET_SSE_MATH && !TARGET_64BIT"
+ "!TARGET_64BIT && TARGET_SSE_MATH"
"x86_emit_floatuns (operands); DONE;")
(define_expand "floatunsdisf2"
[(use (match_operand:SF 0 "register_operand" ""))
(use (match_operand:DI 1 "register_operand" ""))]
- "TARGET_SSE && TARGET_SSE_MATH && TARGET_64BIT"
+ "TARGET_64BIT && TARGET_SSE_MATH"
"x86_emit_floatuns (operands); DONE;")
(define_expand "floatunsdidf2"
[(use (match_operand:DF 0 "register_operand" ""))
(use (match_operand:DI 1 "register_operand" ""))]
- "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_64BIT"
+ "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
"x86_emit_floatuns (operands); DONE;")
;; SSE extract/set expanders
-(define_expand "vec_setv2df"
- [(match_operand:V2DF 0 "register_operand" "")
- (match_operand:DF 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_SSE2"
-{
- switch (INTVAL (operands[2]))
- {
- case 0:
- emit_insn (gen_sse2_movsd (operands[0], operands[0],
- simplify_gen_subreg (V2DFmode, operands[1],
- DFmode, 0)));
- break;
- case 1:
- {
- rtx op1 = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0);
-
- emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], op1));
- }
- break;
- default:
- abort ();
- }
- DONE;
-})
-
-(define_expand "vec_extractv2df"
- [(match_operand:DF 0 "register_operand" "")
- (match_operand:V2DF 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_SSE2"
-{
- switch (INTVAL (operands[2]))
- {
- case 0:
- emit_move_insn (operands[0], gen_lowpart (DFmode, operands[1]));
- break;
- case 1:
- {
- rtx dest = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
-
- emit_insn (gen_sse2_unpckhpd (dest, operands[1], operands[1]));
- }
- break;
- default:
- abort ();
- }
- DONE;
-})
-
-(define_expand "vec_initv2df"
- [(match_operand:V2DF 0 "register_operand" "")
- (match_operand 1 "" "")]
- "TARGET_SSE2"
-{
- ix86_expand_vector_init (operands[0], operands[1]);
- DONE;
-})
-
-(define_expand "vec_setv4sf"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:SF 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_SSE"
-{
- switch (INTVAL (operands[2]))
- {
- case 0:
- emit_insn (gen_sse_movss (operands[0], operands[0],
- simplify_gen_subreg (V4SFmode, operands[1],
- SFmode, 0)));
- break;
- case 1:
- {
- rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
- rtx tmp = gen_reg_rtx (V4SFmode);
-
- emit_move_insn (tmp, operands[0]);
- emit_insn (gen_sse_unpcklps (operands[0], operands[0], operands[0]));
- emit_insn (gen_sse_movss (operands[0], operands[0], op1));
- emit_insn (gen_sse_shufps (operands[0], operands[0], tmp,
- GEN_INT (1 + (0<<2) + (2<<4) + (3<<6))));
- }
- case 2:
- {
- rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
- rtx tmp = gen_reg_rtx (V4SFmode);
-
- emit_move_insn (tmp, operands[0]);
- emit_insn (gen_sse_movss (tmp, tmp, op1));
- emit_insn (gen_sse_shufps (operands[0], operands[0], tmp,
- GEN_INT (0 + (1<<2) + (0<<4) + (3<<6))));
- }
- break;
- case 3:
- {
- rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
- rtx tmp = gen_reg_rtx (V4SFmode);
+
+;; Add instructions
- emit_move_insn (tmp, operands[0]);
- emit_insn (gen_sse_movss (tmp, tmp, op1));
- emit_insn (gen_sse_shufps (operands[0], operands[0], tmp,
- GEN_INT (0 + (1<<2) + (2<<4) + (0<<6))));
- }
- break;
- default:
- abort ();
- }
- DONE;
-})
+;; %%% splits for addditi3
-(define_expand "vec_extractv4sf"
- [(match_operand:SF 0 "register_operand" "")
- (match_operand:V4SF 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_SSE"
-{
- switch (INTVAL (operands[2]))
- {
- case 0:
- emit_move_insn (operands[0], gen_lowpart (SFmode, operands[1]));
- break;
- case 1:
- {
- rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
- rtx tmp = gen_reg_rtx (V4SFmode);
-
- emit_move_insn (tmp, operands[1]);
- emit_insn (gen_sse_shufps (op0, tmp, tmp,
- GEN_INT (1)));
- }
- case 2:
- {
- rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
- rtx tmp = gen_reg_rtx (V4SFmode);
-
- emit_move_insn (tmp, operands[1]);
- emit_insn (gen_sse_unpckhps (op0, tmp, tmp));
- }
- case 3:
- {
- rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
- rtx tmp = gen_reg_rtx (V4SFmode);
-
- emit_move_insn (tmp, operands[1]);
- emit_insn (gen_sse_shufps (op0, tmp, tmp,
- GEN_INT (3)));
- }
- default:
- abort ();
- }
- DONE;
-})
+(define_expand "addti3"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "x86_64_general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "ix86_expand_binary_operator (PLUS, TImode, operands); DONE;")
+
+(define_insn "*addti3_1"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
+ (plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:TI 2 "general_operand" "roiF,riF")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && ix86_binary_operator_ok (PLUS, TImode, operands)"
+ "#")
-(define_expand "vec_initv4sf"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand 1 "" "")]
- "TARGET_SSE"
-{
- ix86_expand_vector_init (operands[0], operands[1]);
- DONE;
-})
-
-;; Add instructions
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (plus:TI (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
+ UNSPEC_ADD_CARRY))
+ (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))])
+ (parallel [(set (match_dup 3)
+ (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 4))
+ (match_dup 5)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_ti (operands+0, 1, operands+0, operands+3);
+ split_ti (operands+1, 1, operands+1, operands+4);
+ split_ti (operands+2, 1, operands+2, operands+5);")
;; %%% splits for addsidi3
; [(set (match_operand:DI 0 "nonimmediate_operand" "")
@@ -4926,7 +4781,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "x86_64_general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (PLUS, DImode, operands); DONE;")
@@ -4934,7 +4789,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "roiF,riF")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
"#")
@@ -4942,16 +4797,16 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && reload_completed"
- [(parallel [(set (reg:CC 17) (unspec:CC [(match_dup 1) (match_dup 2)]
+ [(parallel [(set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 1) (match_dup 2)]
UNSPEC_ADD_CARRY))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
(parallel [(set (match_dup 3)
- (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+ (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
(match_dup 4))
(match_dup 5)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"split_di (operands+0, 1, operands+0, operands+3);
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
@@ -4961,16 +4816,15 @@
(plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
(match_operand:DI 1 "nonimmediate_operand" "%0,0"))
(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
"adc{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "mode" "DI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "DI")])
(define_insn "*adddi3_cc_rex64"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rm")]
UNSPEC_ADD_CARRY))
@@ -4986,39 +4840,36 @@
(plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
(match_operand:QI 1 "nonimmediate_operand" "%0,0"))
(match_operand:QI 2 "general_operand" "qi,qm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, QImode, operands)"
"adc{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "mode" "QI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "QI")])
(define_insn "addhi3_carry"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
(plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
(match_operand:HI 1 "nonimmediate_operand" "%0,0"))
(match_operand:HI 2 "general_operand" "ri,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, HImode, operands)"
"adc{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "mode" "HI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "HI")])
(define_insn "addsi3_carry"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
(match_operand:SI 1 "nonimmediate_operand" "%0,0"))
(match_operand:SI 2 "general_operand" "ri,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, SImode, operands)"
"adc{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "mode" "SI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "SI")])
(define_insn "*addsi3_carry_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5026,16 +4877,15 @@
(plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
(match_operand:SI 1 "nonimmediate_operand" "%0"))
(match_operand:SI 2 "general_operand" "rim"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
"adc{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "mode" "SI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "SI")])
(define_insn "*addsi3_cc"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "ri,rm")]
UNSPEC_ADD_CARRY))
@@ -5047,7 +4897,7 @@
(set_attr "mode" "SI")])
(define_insn "addqi3_cc"
- [(set (reg:CC 17)
+ [(set (reg:CC FLAGS_REG)
(unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
(match_operand:QI 2 "general_operand" "qi,qm")]
UNSPEC_ADD_CARRY))
@@ -5062,7 +4912,7 @@
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"ix86_expand_binary_operator (PLUS, SImode, operands); DONE;")
@@ -5104,7 +4954,7 @@
(define_insn_and_split "*lea_general_1"
[(set (match_operand 0 "register_operand" "=r")
- (plus (plus (match_operand 1 "index_register_operand" "r")
+ (plus (plus (match_operand 1 "index_register_operand" "l")
(match_operand 2 "register_operand" "r"))
(match_operand 3 "immediate_operand" "i")))]
"(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
@@ -5136,7 +4986,7 @@
(define_insn_and_split "*lea_general_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "r")
+ (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "l")
(match_operand:SI 2 "register_operand" "r"))
(match_operand:SI 3 "immediate_operand" "i"))))]
"TARGET_64BIT"
@@ -5156,7 +5006,7 @@
(define_insn_and_split "*lea_general_2"
[(set (match_operand 0 "register_operand" "=r")
- (plus (mult (match_operand 1 "index_register_operand" "r")
+ (plus (mult (match_operand 1 "index_register_operand" "l")
(match_operand 2 "const248_operand" "i"))
(match_operand 3 "nonmemory_operand" "ri")))]
"(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
@@ -5186,7 +5036,7 @@
(define_insn_and_split "*lea_general_2_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "r")
+ (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "l")
(match_operand:SI 2 "const248_operand" "n"))
(match_operand:SI 3 "nonmemory_operand" "ri"))))]
"TARGET_64BIT"
@@ -5205,7 +5055,7 @@
(define_insn_and_split "*lea_general_3"
[(set (match_operand 0 "register_operand" "=r")
- (plus (plus (mult (match_operand 1 "index_register_operand" "r")
+ (plus (plus (mult (match_operand 1 "index_register_operand" "l")
(match_operand 2 "const248_operand" "i"))
(match_operand 3 "register_operand" "r"))
(match_operand 4 "immediate_operand" "i")))]
@@ -5239,8 +5089,9 @@
(define_insn_and_split "*lea_general_3_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "r")
- (match_operand:SI 2 "const248_operand" "n"))
+ (plus:SI (plus:SI (mult:SI
+ (match_operand:SI 1 "index_register_operand" "l")
+ (match_operand:SI 2 "const248_operand" "n"))
(match_operand:SI 3 "register_operand" "r"))
(match_operand:SI 4 "immediate_operand" "i"))))]
"TARGET_64BIT"
@@ -5262,8 +5113,8 @@
(define_insn "*adddi_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r")
- (match_operand:DI 2 "x86_64_general_operand" "rme,re,re")))
- (clobber (reg:CC 17))]
+ (match_operand:DI 2 "x86_64_general_operand" "rme,re,le")))
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
{
switch (get_attr_type (insn))
@@ -5273,18 +5124,17 @@
return "lea{q}\t{%a2, %0|%0, %a2}";
case TYPE_INCDEC:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
return "inc{q}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{q}\t%0";
else
- abort ();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{q}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
@@ -5319,7 +5169,7 @@
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "x86_64_nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(set (match_dup 0)
@@ -5328,7 +5178,7 @@
"")
(define_insn "*adddi_2_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "x86_64_general_operand" "rme,re"))
@@ -5344,18 +5194,17 @@
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
return "inc{q}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{q}\t%0";
else
- abort ();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{q}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* ???? We ought to handle there the 32bit case too
- do we need new constraint? */
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -5380,7 +5229,7 @@
(set_attr "mode" "DI")])
(define_insn "*adddi_3_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme"))
(match_operand:DI 1 "x86_64_general_operand" "%0")))
(clobber (match_scratch:DI 0 "=r"))]
@@ -5394,18 +5243,17 @@
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
return "inc{q}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{q}\t%0";
else
- abort ();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{q}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* ???? We ought to handle there the 32bit case too
- do we need new constraint? */
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -5438,7 +5286,7 @@
; Also carry flag is reversed compared to cmp, so this conversion is valid
; only for comparisons not depending on it.
(define_insn "*adddi_4_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:DI 2 "x86_64_immediate_operand" "e")))
(clobber (match_scratch:DI 0 "=rm"))]
@@ -5450,14 +5298,14 @@
case TYPE_INCDEC:
if (operands[2] == constm1_rtx)
return "inc{q}\t%0";
- else if (operands[2] == const1_rtx)
- return "dec{q}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == const1_rtx);
+ return "dec{q}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if ((INTVAL (operands[2]) == -128
@@ -5477,7 +5325,7 @@
(set_attr "mode" "DI")])
(define_insn "*adddi_5_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "x86_64_general_operand" "rme"))
@@ -5493,18 +5341,17 @@
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
return "inc{q}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{q}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{q}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
@@ -5530,8 +5377,8 @@
(define_insn "*addsi_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
- (match_operand:SI 2 "general_operand" "rmni,rni,rni")))
- (clobber (reg:CC 17))]
+ (match_operand:SI 2 "general_operand" "rmni,rni,lni")))
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, SImode, operands)"
{
switch (get_attr_type (insn))
@@ -5541,18 +5388,17 @@
return "lea{l}\t{%a2, %0|%0, %a2}";
case TYPE_INCDEC:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
return "inc{l}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{l}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{l}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
@@ -5585,7 +5431,7 @@
[(set (match_operand 0 "register_operand" "")
(plus (match_operand 1 "register_operand" "")
(match_operand 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(const_int 0)]
@@ -5615,8 +5461,8 @@
[(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
- (match_operand:SI 2 "general_operand" "rmni,rni"))))
- (clobber (reg:CC 17))]
+ (match_operand:SI 2 "general_operand" "rmni,lni"))))
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
{
switch (get_attr_type (insn))
@@ -5628,10 +5474,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{l}\t%k0";
- else if (operands[2] == constm1_rtx)
- return "dec{l}\t%k0";
else
- abort();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{l}\t%k0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -5666,7 +5513,7 @@
(zero_extend:DI
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" ""))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(set (match_dup 0)
@@ -5677,7 +5524,7 @@
})
(define_insn "*addsi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "rmni,rni"))
@@ -5693,18 +5540,17 @@
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
return "inc{l}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{l}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{l}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
@@ -5726,7 +5572,7 @@
;; See comment for addsi_1_zext why we do use nonimmediate_operand
(define_insn "*addsi_2_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rmni"))
@@ -5744,10 +5590,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{l}\t%k0";
- else if (operands[2] == constm1_rtx)
- return "dec{l}\t%k0";
else
- abort();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{l}\t%k0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -5770,7 +5617,7 @@
(set_attr "mode" "SI")])
(define_insn "*addsi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
(match_operand:SI 1 "nonimmediate_operand" "%0")))
(clobber (match_scratch:SI 0 "=r"))]
@@ -5783,18 +5630,17 @@
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
return "inc{l}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{l}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{l}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
@@ -5816,7 +5662,7 @@
;; See comment for addsi_1_zext why we do use nonimmediate_operand
(define_insn "*addsi_3_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
(match_operand:SI 1 "nonimmediate_operand" "%0")))
(set (match_operand:DI 0 "register_operand" "=r")
@@ -5832,10 +5678,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{l}\t%k0";
- else if (operands[2] == constm1_rtx)
- return "dec{l}\t%k0";
else
- abort();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{l}\t%k0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -5866,7 +5713,7 @@
; Also carry flag is reversed compared to cmp, so this conversion is valid
; only for comparisons not depending on it.
(define_insn "*addsi_4"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))
(clobber (match_scratch:SI 0 "=rm"))]
@@ -5878,14 +5725,14 @@
case TYPE_INCDEC:
if (operands[2] == constm1_rtx)
return "inc{l}\t%0";
- else if (operands[2] == const1_rtx)
- return "dec{l}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == const1_rtx);
+ return "dec{l}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if ((INTVAL (operands[2]) == -128
@@ -5903,7 +5750,7 @@
(set_attr "mode" "SI")])
(define_insn "*addsi_5"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rmni"))
@@ -5918,18 +5765,17 @@
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (operands[2] == const1_rtx)
return "inc{l}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{l}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{l}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if (GET_CODE (operands[2]) == CONST_INT
@@ -5953,7 +5799,7 @@
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
@@ -5964,8 +5810,8 @@
(define_insn "*addhi_1_lea"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
- (match_operand:HI 2 "general_operand" "ri,rm,rni")))
- (clobber (reg:CC 17))]
+ (match_operand:HI 2 "general_operand" "ri,rm,lni")))
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (PLUS, HImode, operands)"
{
@@ -5976,9 +5822,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{w}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{w}\t%0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6006,7 +5854,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "ri,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (PLUS, HImode, operands)"
{
@@ -6015,9 +5863,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{w}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{w}\t%0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6040,7 +5890,7 @@
(set_attr "mode" "HI")])
(define_insn "*addhi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "rmni,rni"))
@@ -6055,9 +5905,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{w}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{w}\t%0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6080,7 +5932,7 @@
(set_attr "mode" "HI")])
(define_insn "*addhi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (neg:HI (match_operand:HI 2 "general_operand" "rmni"))
(match_operand:HI 1 "nonimmediate_operand" "%0")))
(clobber (match_scratch:HI 0 "=r"))]
@@ -6092,9 +5944,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{w}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{w}\t%0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6116,9 +5970,9 @@
(const_string "alu")))
(set_attr "mode" "HI")])
-; See comments above addsi_3_imm for details.
+; See comments above addsi_4 for details.
(define_insn "*addhi_4"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:HI 2 "const_int_operand" "n")))
(clobber (match_scratch:HI 0 "=rm"))]
@@ -6130,14 +5984,14 @@
case TYPE_INCDEC:
if (operands[2] == constm1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == const1_rtx)
- return "dec{w}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == const1_rtx);
+ return "dec{w}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
Exceptions: -128 encodes smaller than 128, so swap sign and op. */
if ((INTVAL (operands[2]) == -128
@@ -6156,7 +6010,7 @@
(define_insn "*addhi_5"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
(match_operand:HI 2 "general_operand" "rmni"))
@@ -6170,9 +6024,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx)
- return "dec{w}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{w}\t%0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6198,7 +6054,7 @@
[(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
(plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (PLUS, QImode, operands); DONE;")
@@ -6206,8 +6062,8 @@
(define_insn "*addqi_1_lea"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r")
(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,r")
- (match_operand:QI 2 "general_operand" "qn,qmn,rn,rn")))
- (clobber (reg:CC 17))]
+ (match_operand:QI 2 "general_operand" "qn,qmn,rn,ln")))
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (PLUS, QImode, operands)"
{
@@ -6219,9 +6075,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
- else if (operands[2] == constm1_rtx)
- return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6255,7 +6113,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:QI 2 "general_operand" "qn,qmn,rn")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (PLUS, QImode, operands)"
{
@@ -6265,9 +6123,11 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
- else if (operands[2] == constm1_rtx)
- return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx);
+ return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6299,7 +6159,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
(plus:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qn,qnm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
{
@@ -6308,9 +6168,11 @@
case TYPE_INCDEC:
if (operands[1] == const1_rtx)
return "inc{b}\t%0";
- else if (operands[1] == constm1_rtx)
- return "dec{b}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[1] == constm1_rtx);
+ return "dec{b}\t%0";
+ }
default:
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. */
@@ -6334,7 +6196,7 @@
(set_attr "mode" "QI")])
(define_insn "*addqi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
(match_operand:QI 2 "general_operand" "qmni,qni"))
@@ -6349,11 +6211,13 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{b}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 255))
- return "dec{b}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx
+ || (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 255));
+ return "dec{b}\t%0";
+ }
default:
/* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */
@@ -6373,7 +6237,7 @@
(set_attr "mode" "QI")])
(define_insn "*addqi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (neg:QI (match_operand:QI 2 "general_operand" "qmni"))
(match_operand:QI 1 "nonimmediate_operand" "%0")))
(clobber (match_scratch:QI 0 "=q"))]
@@ -6385,11 +6249,13 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{b}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 255))
- return "dec{b}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx
+ || (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 255));
+ return "dec{b}\t%0";
+ }
default:
/* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */
@@ -6408,9 +6274,9 @@
(const_string "alu")))
(set_attr "mode" "QI")])
-; See comments above addsi_3_imm for details.
+; See comments above addsi_4 for details.
(define_insn "*addqi_4"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const_int_operand" "n")))
(clobber (match_scratch:QI 0 "=qm"))]
@@ -6424,14 +6290,14 @@
|| (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 255))
return "inc{b}\t%0";
- else if (operands[2] == const1_rtx)
- return "dec{b}\t%0";
else
- abort();
+ {
+ gcc_assert (operands[2] == const1_rtx);
+ return "dec{b}\t%0";
+ }
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (INTVAL (operands[2]) < 0)
{
operands[2] = GEN_INT (-INTVAL (operands[2]));
@@ -6448,7 +6314,7 @@
(define_insn "*addqi_5"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
(match_operand:QI 2 "general_operand" "qmni"))
@@ -6462,11 +6328,13 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{b}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 255))
- return "dec{b}\t%0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx
+ || (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 255));
+ return "dec{b}\t%0";
+ }
default:
/* Make things pretty and `subb $4,%al' rather than `addb $-4, %al'. */
@@ -6496,7 +6364,7 @@
(const_int 8)
(const_int 8))
(match_operand:QI 2 "general_operand" "Qmn")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
{
switch (get_attr_type (insn))
@@ -6504,11 +6372,13 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{b}\t%h0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 255))
- return "dec{b}\t%h0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx
+ || (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 255));
+ return "dec{b}\t%h0";
+ }
default:
return "add{b}\t{%2, %h0|%h0, %2}";
@@ -6530,7 +6400,7 @@
(const_int 8)
(const_int 8))
(match_operand:QI 2 "nonmemory_operand" "Qn")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
{
switch (get_attr_type (insn))
@@ -6538,11 +6408,13 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{b}\t%h0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 255))
- return "dec{b}\t%h0";
- abort();
+ else
+ {
+ gcc_assert (operands[2] == constm1_rtx
+ || (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 255));
+ return "dec{b}\t%h0";
+ }
default:
return "add{b}\t{%2, %h0|%h0, %2}";
@@ -6567,7 +6439,7 @@
(match_operand 2 "ext_register_operand" "Q")
(const_int 8)
(const_int 8))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"add{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
@@ -6598,13 +6470,48 @@
;; Subtract instructions
+;; %%% splits for subditi3
+
+(define_expand "subti3"
+ [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "x86_64_general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
+ "ix86_expand_binary_operator (MINUS, TImode, operands); DONE;")
+
+(define_insn "*subti3_1"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
+ (minus:TI (match_operand:TI 1 "nonimmediate_operand" "0,0")
+ (match_operand:TI 2 "general_operand" "roiF,riF")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && ix86_binary_operator_ok (MINUS, TImode, operands)"
+ "#")
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (minus:TI (match_operand:TI 1 "nonimmediate_operand" "")
+ (match_operand:TI 2 "general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))])
+ (parallel [(set (match_dup 3)
+ (minus:DI (match_dup 4)
+ (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 5))))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_ti (operands+0, 1, operands+0, operands+3);
+ split_ti (operands+1, 1, operands+1, operands+4);
+ split_ti (operands+2, 1, operands+2, operands+5);")
+
;; %%% splits for subsidi3
(define_expand "subdi3"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "x86_64_general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"ix86_expand_binary_operator (MINUS, DImode, operands); DONE;")
@@ -6612,7 +6519,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:DI 2 "general_operand" "roiF,riF")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
"#")
@@ -6620,15 +6527,15 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && reload_completed"
- [(parallel [(set (reg:CC 17) (compare:CC (match_dup 1) (match_dup 2)))
+ [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_dup 1) (match_dup 2)))
(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
(parallel [(set (match_dup 3)
(minus:SI (match_dup 4)
- (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+ (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
(match_dup 5))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"split_di (operands+0, 1, operands+0, operands+3);
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
@@ -6638,26 +6545,25 @@
(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
(match_operand:DI 2 "x86_64_general_operand" "re,rm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
"sbb{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "ppro_uops" "few")
(set_attr "mode" "DI")])
(define_insn "*subdi_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
"sub{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
(define_insn "*subdi_2_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rm"))
@@ -6671,7 +6577,7 @@
(set_attr "mode" "DI")])
(define_insn "*subdi_3_rex63"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
@@ -6687,12 +6593,11 @@
(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
(match_operand:QI 2 "general_operand" "qi,qm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, QImode, operands)"
"sbb{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "ppro_uops" "few")
(set_attr "mode" "QI")])
(define_insn "subhi3_carry"
@@ -6700,12 +6605,11 @@
(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
(plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
(match_operand:HI 2 "general_operand" "ri,rm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, HImode, operands)"
"sbb{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "ppro_uops" "few")
(set_attr "mode" "HI")])
(define_insn "subsi3_carry"
@@ -6713,12 +6617,11 @@
(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
(match_operand:SI 2 "general_operand" "ri,rm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, SImode, operands)"
"sbb{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "ppro_uops" "few")
(set_attr "mode" "SI")])
(define_insn "subsi3_carry_zext"
@@ -6727,19 +6630,18 @@
(minus:SI (match_operand:SI 1 "register_operand" "0,0")
(plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
(match_operand:SI 2 "general_operand" "ri,rm")))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sbb{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "pent_pair" "pu")
- (set_attr "ppro_uops" "few")
(set_attr "mode" "SI")])
(define_expand "subsi3"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"ix86_expand_binary_operator (MINUS, SImode, operands); DONE;")
@@ -6747,7 +6649,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:SI 2 "general_operand" "ri,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
@@ -6758,14 +6660,14 @@
(zero_extend:DI
(minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "rim"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*subsi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:SI 2 "general_operand" "ri,rm"))
@@ -6779,7 +6681,7 @@
(set_attr "mode" "SI")])
(define_insn "*subsi_2_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "rim"))
@@ -6795,7 +6697,7 @@
(set_attr "mode" "SI")])
(define_insn "*subsi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:SI 2 "general_operand" "ri,rm")))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
@@ -6807,7 +6709,7 @@
(set_attr "mode" "SI")])
(define_insn "*subsi_3_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "rim")))
(set (match_operand:DI 0 "register_operand" "=r")
@@ -6816,7 +6718,7 @@
(match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
&& ix86_binary_operator_ok (MINUS, SImode, operands)"
- "sub{q}\t{%2, %0|%0, %2}"
+ "sub{l}\t{%2, %1|%1, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
@@ -6824,7 +6726,7 @@
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (MINUS, HImode, operands); DONE;")
@@ -6832,14 +6734,14 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
(match_operand:HI 2 "general_operand" "ri,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, HImode, operands)"
"sub{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "HI")])
(define_insn "*subhi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
(match_operand:HI 2 "general_operand" "ri,rm"))
@@ -6853,7 +6755,7 @@
(set_attr "mode" "HI")])
(define_insn "*subhi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:HI 1 "nonimmediate_operand" "0,0")
(match_operand:HI 2 "general_operand" "ri,rm")))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
@@ -6868,7 +6770,7 @@
[(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
(minus:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (MINUS, QImode, operands); DONE;")
@@ -6876,7 +6778,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "general_operand" "qn,qmn")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, QImode, operands)"
"sub{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
@@ -6886,7 +6788,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
(minus:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qn,qmn")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"sub{b}\t{%1, %0|%0, %1}"
@@ -6894,7 +6796,7 @@
(set_attr "mode" "QI")])
(define_insn "*subqi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "general_operand" "qi,qm"))
@@ -6908,7 +6810,7 @@
(set_attr "mode" "QI")])
(define_insn "*subqi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "general_operand" "qi,qm")))
(set (match_operand:HI 0 "nonimmediate_operand" "=qm,q")
@@ -6948,7 +6850,7 @@
[(parallel [(set (match_operand:DI 0 "register_operand" "")
(mult:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "x86_64_general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_64BIT"
"")
@@ -6956,7 +6858,7 @@
[(set (match_operand:DI 0 "register_operand" "=r,r,r")
(mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,rm,0")
(match_operand:DI 2 "x86_64_general_operand" "K,e,mr")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"@
@@ -6980,7 +6882,7 @@
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(mult:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
@@ -6988,7 +6890,7 @@
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
(match_operand:SI 2 "general_operand" "K,i,mr")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
"@
imul{l}\t{%2, %1, %0|%0, %1, %2}
@@ -7012,7 +6914,7 @@
(zero_extend:DI
(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
(match_operand:SI 2 "general_operand" "K,i,mr"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"@
@@ -7036,7 +6938,7 @@
[(parallel [(set (match_operand:HI 0 "register_operand" "")
(mult:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "general_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_HIMODE_MATH"
"")
@@ -7044,7 +6946,7 @@
[(set (match_operand:HI 0 "register_operand" "=r,r,r")
(mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,rm,0")
(match_operand:HI 2 "general_operand" "K,i,mr")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
"@
imul{w}\t{%2, %1, %0|%0, %1, %2}
@@ -7064,7 +6966,7 @@
[(parallel [(set (match_operand:QI 0 "register_operand" "")
(mult:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "register_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_QIMODE_MATH"
"")
@@ -7072,7 +6974,7 @@
[(set (match_operand:QI 0 "register_operand" "=a")
(mult:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
(match_operand:QI 2 "nonimmediate_operand" "qm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"mul{b}\t%2"
@@ -7090,7 +6992,7 @@
(match_operand:QI 1 "nonimmediate_operand" ""))
(zero_extend:HI
(match_operand:QI 2 "register_operand" ""))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_QIMODE_MATH"
"")
@@ -7098,7 +7000,7 @@
[(set (match_operand:HI 0 "register_operand" "=a")
(mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
(zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"mul{b}\t%2"
@@ -7114,7 +7016,7 @@
[(parallel [(set (match_operand:HI 0 "register_operand" "")
(mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" ""))
(sign_extend:HI (match_operand:QI 2 "register_operand" ""))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_QIMODE_MATH"
"")
@@ -7122,7 +7024,7 @@
[(set (match_operand:HI 0 "register_operand" "=a")
(mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
(sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"imul{b}\t%2"
@@ -7140,7 +7042,7 @@
(match_operand:DI 1 "nonimmediate_operand" ""))
(zero_extend:TI
(match_operand:DI 2 "register_operand" ""))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_64BIT"
"")
@@ -7148,12 +7050,11 @@
[(set (match_operand:TI 0 "register_operand" "=A")
(mult:TI (zero_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
(zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"mul{q}\t%2"
[(set_attr "type" "imul")
- (set_attr "ppro_uops" "few")
(set_attr "length_immediate" "0")
(set (attr "athlon_decode")
(if_then_else (eq_attr "cpu" "athlon")
@@ -7168,7 +7069,7 @@
(match_operand:SI 1 "nonimmediate_operand" ""))
(zero_extend:DI
(match_operand:SI 2 "register_operand" ""))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"!TARGET_64BIT"
"")
@@ -7176,12 +7077,11 @@
[(set (match_operand:DI 0 "register_operand" "=A")
(mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
(zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"mul{l}\t%2"
[(set_attr "type" "imul")
- (set_attr "ppro_uops" "few")
(set_attr "length_immediate" "0")
(set (attr "athlon_decode")
(if_then_else (eq_attr "cpu" "athlon")
@@ -7195,7 +7095,7 @@
(match_operand:DI 1 "nonimmediate_operand" ""))
(sign_extend:TI
(match_operand:DI 2 "register_operand" ""))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_64BIT"
"")
@@ -7203,7 +7103,7 @@
[(set (match_operand:TI 0 "register_operand" "=A")
(mult:TI (sign_extend:TI (match_operand:DI 1 "nonimmediate_operand" "%0"))
(sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"imul{q}\t%2"
@@ -7221,7 +7121,7 @@
(match_operand:SI 1 "nonimmediate_operand" ""))
(sign_extend:DI
(match_operand:SI 2 "register_operand" ""))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"!TARGET_64BIT"
"")
@@ -7229,7 +7129,7 @@
[(set (match_operand:DI 0 "register_operand" "=A")
(mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%0"))
(sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"imul{l}\t%2"
@@ -7251,7 +7151,7 @@
(match_operand:DI 2 "register_operand" "")))
(const_int 64))))
(clobber (match_scratch:DI 3 ""))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_64BIT"
"")
@@ -7265,12 +7165,11 @@
(match_operand:DI 2 "nonimmediate_operand" "rm")))
(const_int 64))))
(clobber (match_scratch:DI 3 "=1"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"mul{q}\t%2"
[(set_attr "type" "imul")
- (set_attr "ppro_uops" "few")
(set_attr "length_immediate" "0")
(set (attr "athlon_decode")
(if_then_else (eq_attr "cpu" "athlon")
@@ -7288,7 +7187,7 @@
(match_operand:SI 2 "register_operand" "")))
(const_int 32))))
(clobber (match_scratch:SI 3 ""))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
@@ -7302,11 +7201,10 @@
(match_operand:SI 2 "nonimmediate_operand" "rm")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=1"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
"mul{l}\t%2"
[(set_attr "type" "imul")
- (set_attr "ppro_uops" "few")
(set_attr "length_immediate" "0")
(set (attr "athlon_decode")
(if_then_else (eq_attr "cpu" "athlon")
@@ -7324,12 +7222,11 @@
(match_operand:SI 2 "nonimmediate_operand" "rm")))
(const_int 32)))))
(clobber (match_scratch:SI 3 "=1"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"mul{l}\t%2"
[(set_attr "type" "imul")
- (set_attr "ppro_uops" "few")
(set_attr "length_immediate" "0")
(set (attr "athlon_decode")
(if_then_else (eq_attr "cpu" "athlon")
@@ -7347,7 +7244,7 @@
(match_operand:DI 2 "register_operand" "")))
(const_int 64))))
(clobber (match_scratch:DI 3 ""))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_64BIT"
"")
@@ -7361,12 +7258,11 @@
(match_operand:DI 2 "nonimmediate_operand" "rm")))
(const_int 64))))
(clobber (match_scratch:DI 3 "=1"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"imul{q}\t%2"
[(set_attr "type" "imul")
- (set_attr "ppro_uops" "few")
(set (attr "athlon_decode")
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
@@ -7383,7 +7279,7 @@
(match_operand:SI 2 "register_operand" "")))
(const_int 32))))
(clobber (match_scratch:SI 3 ""))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
@@ -7397,11 +7293,10 @@
(match_operand:SI 2 "nonimmediate_operand" "rm")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=1"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM"
"imul{l}\t%2"
[(set_attr "type" "imul")
- (set_attr "ppro_uops" "few")
(set (attr "athlon_decode")
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
@@ -7418,12 +7313,11 @@
(match_operand:SI 2 "nonimmediate_operand" "rm")))
(const_int 32)))))
(clobber (match_scratch:SI 3 "=1"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"imul{l}\t%2"
[(set_attr "type" "imul")
- (set_attr "ppro_uops" "few")
(set (attr "athlon_decode")
(if_then_else (eq_attr "cpu" "athlon")
(const_string "vector")
@@ -7459,23 +7353,21 @@
[(set (match_operand:QI 0 "register_operand" "=a")
(div:QI (match_operand:HI 1 "register_operand" "0")
(match_operand:QI 2 "nonimmediate_operand" "qm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"idiv{b}\t%2"
[(set_attr "type" "idiv")
- (set_attr "mode" "QI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "QI")])
(define_insn "udivqi3"
[(set (match_operand:QI 0 "register_operand" "=a")
(udiv:QI (match_operand:HI 1 "register_operand" "0")
(match_operand:QI 2 "nonimmediate_operand" "qm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"div{b}\t%2"
[(set_attr "type" "idiv")
- (set_attr "mode" "QI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "QI")])
;; The patterns that match these are at the end of this file.
@@ -7508,7 +7400,7 @@
(match_operand:DI 2 "nonimmediate_operand" "")))
(set (match_operand:DI 3 "register_operand" "")
(mod:DI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_64BIT"
"")
@@ -7521,7 +7413,7 @@
(match_operand:DI 3 "nonimmediate_operand" "rm,rm")))
(set (match_operand:DI 1 "register_operand" "=&d,&d")
(mod:DI (match_dup 2) (match_dup 3)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && !optimize_size && !TARGET_USE_CLTD"
"#"
[(set_attr "type" "multi")])
@@ -7532,7 +7424,7 @@
(match_operand:DI 3 "nonimmediate_operand" "rm")))
(set (match_operand:DI 1 "register_operand" "=&d")
(mod:DI (match_dup 2) (match_dup 3)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && (optimize_size || TARGET_USE_CLTD)"
"#"
[(set_attr "type" "multi")])
@@ -7544,12 +7436,11 @@
(set (match_operand:DI 3 "register_operand" "=d")
(mod:DI (match_dup 1) (match_dup 2)))
(use (match_operand:DI 4 "register_operand" "3"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"idiv{q}\t%2"
[(set_attr "type" "idiv")
- (set_attr "mode" "DI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "DI")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -7557,17 +7448,17 @@
(match_operand:DI 2 "nonimmediate_operand" "")))
(set (match_operand:DI 3 "register_operand" "")
(mod:DI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && reload_completed"
[(parallel [(set (match_dup 3)
(ashiftrt:DI (match_dup 4) (const_int 63)))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(parallel [(set (match_dup 0)
(div:DI (reg:DI 0) (match_dup 2)))
(set (match_dup 3)
(mod:DI (reg:DI 0) (match_dup 2)))
(use (match_dup 3))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
{
/* Avoid use of cltd in favor of a mov+shift. */
if (!TARGET_USE_CLTD && !optimize_size)
@@ -7580,8 +7471,7 @@
}
else
{
- if (true_regnum (operands[1]))
- abort();
+ gcc_assert (!true_regnum (operands[1]));
operands[4] = operands[1];
}
})
@@ -7593,7 +7483,7 @@
(match_operand:SI 2 "nonimmediate_operand" "")))
(set (match_operand:SI 3 "register_operand" "")
(mod:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
@@ -7606,7 +7496,7 @@
(match_operand:SI 3 "nonimmediate_operand" "rm,rm")))
(set (match_operand:SI 1 "register_operand" "=&d,&d")
(mod:SI (match_dup 2) (match_dup 3)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!optimize_size && !TARGET_USE_CLTD"
"#"
[(set_attr "type" "multi")])
@@ -7617,7 +7507,7 @@
(match_operand:SI 3 "nonimmediate_operand" "rm")))
(set (match_operand:SI 1 "register_operand" "=&d")
(mod:SI (match_dup 2) (match_dup 3)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"optimize_size || TARGET_USE_CLTD"
"#"
[(set_attr "type" "multi")])
@@ -7629,12 +7519,11 @@
(set (match_operand:SI 3 "register_operand" "=d")
(mod:SI (match_dup 1) (match_dup 2)))
(use (match_operand:SI 4 "register_operand" "3"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"idiv{l}\t%2"
[(set_attr "type" "idiv")
- (set_attr "mode" "SI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "SI")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -7642,17 +7531,17 @@
(match_operand:SI 2 "nonimmediate_operand" "")))
(set (match_operand:SI 3 "register_operand" "")
(mod:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed"
[(parallel [(set (match_dup 3)
(ashiftrt:SI (match_dup 4) (const_int 31)))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(parallel [(set (match_dup 0)
(div:SI (reg:SI 0) (match_dup 2)))
(set (match_dup 3)
(mod:SI (reg:SI 0) (match_dup 2)))
(use (match_dup 3))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
{
/* Avoid use of cltd in favor of a mov+shift. */
if (!TARGET_USE_CLTD && !optimize_size)
@@ -7665,8 +7554,7 @@
}
else
{
- if (true_regnum (operands[1]))
- abort();
+ gcc_assert (!true_regnum (operands[1]));
operands[4] = operands[1];
}
})
@@ -7677,7 +7565,7 @@
(match_operand:HI 2 "nonimmediate_operand" "rm")))
(set (match_operand:HI 3 "register_operand" "=&d")
(mod:HI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"cwtd\;idiv{w}\t%2"
[(set_attr "type" "multi")
@@ -7690,7 +7578,7 @@
(match_operand:DI 2 "nonimmediate_operand" "rm")))
(set (match_operand:DI 3 "register_operand" "=&d")
(umod:DI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"xor{q}\t%3, %3\;div{q}\t%2"
[(set_attr "type" "multi")
@@ -7704,11 +7592,10 @@
(set (match_operand:DI 3 "register_operand" "=d")
(umod:DI (match_dup 1) (match_dup 2)))
(use (match_dup 3))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"div{q}\t%2"
[(set_attr "type" "idiv")
- (set_attr "ppro_uops" "few")
(set_attr "mode" "DI")])
(define_split
@@ -7717,7 +7604,7 @@
(match_operand:DI 2 "nonimmediate_operand" "")))
(set (match_operand:DI 3 "register_operand" "")
(umod:DI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && reload_completed"
[(set (match_dup 3) (const_int 0))
(parallel [(set (match_dup 0)
@@ -7725,7 +7612,7 @@
(set (match_dup 3)
(umod:DI (match_dup 1) (match_dup 2)))
(use (match_dup 3))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_insn "udivmodsi4"
@@ -7734,7 +7621,7 @@
(match_operand:SI 2 "nonimmediate_operand" "rm")))
(set (match_operand:SI 3 "register_operand" "=&d")
(umod:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"xor{l}\t%3, %3\;div{l}\t%2"
[(set_attr "type" "multi")
@@ -7748,11 +7635,10 @@
(set (match_operand:SI 3 "register_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))
(use (match_dup 3))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"div{l}\t%2"
[(set_attr "type" "idiv")
- (set_attr "ppro_uops" "few")
(set_attr "mode" "SI")])
(define_split
@@ -7761,7 +7647,7 @@
(match_operand:SI 2 "nonimmediate_operand" "")))
(set (match_operand:SI 3 "register_operand" "")
(umod:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed"
[(set (match_dup 3) (const_int 0))
(parallel [(set (match_dup 0)
@@ -7769,7 +7655,7 @@
(set (match_dup 3)
(umod:SI (match_dup 1) (match_dup 2)))
(use (match_dup 3))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_expand "udivmodhi4"
@@ -7780,7 +7666,7 @@
(set (match_operand:HI 3 "register_operand" "")
(umod:HI (match_dup 1) (match_dup 2)))
(use (match_dup 4))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_HIMODE_MATH"
"operands[4] = gen_reg_rtx (HImode);")
@@ -7791,14 +7677,13 @@
(set (match_operand:HI 3 "register_operand" "=d")
(umod:HI (match_dup 1) (match_dup 2)))
(use (match_operand:HI 4 "register_operand" "3"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"div{w}\t%2"
[(set_attr "type" "idiv")
- (set_attr "mode" "HI")
- (set_attr "ppro_uops" "few")])
+ (set_attr "mode" "HI")])
-;; We can not use div/idiv for double division, because it causes
+;; We cannot use div/idiv for double division, because it causes
;; "division by zero" on the overflow and that's not what we expect
;; from truncate. Because true (non truncating) double division is
;; never generated, we can't create this insn anyway.
@@ -7812,11 +7697,10 @@
; (set (match_operand:SI 3 "register_operand" "=d")
; (truncate:SI
; (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))
-; (clobber (reg:CC 17))]
+; (clobber (reg:CC FLAGS_REG))]
; ""
; "div{l}\t{%2, %0|%0, %2}"
-; [(set_attr "type" "idiv")
-; (set_attr "ppro_uops" "few")])
+; [(set_attr "type" "idiv")])
;;- Logical AND instructions
@@ -7824,7 +7708,7 @@
;; Note that this excludes ah.
(define_insn "*testdi_1_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm")
(match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re"))
@@ -7832,10 +7716,10 @@
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
- test{l}\t{%k1, %k0|%k0, %k1}
- test{l}\t{%k1, %k0|%k0, %k1}
- test{q}\t{%1, %0|%0, %1}
- test{q}\t{%1, %0|%0, %1}
+ test{l}\t{%k1, %k0|%k0, %k1}
+ test{l}\t{%k1, %k0|%k0, %k1}
+ test{q}\t{%1, %0|%0, %1}
+ test{q}\t{%1, %0|%0, %1}
test{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "test")
(set_attr "modrm" "0,1,0,1,1")
@@ -7843,7 +7727,7 @@
(set_attr "pent_pair" "uv,np,uv,np,uv")])
(define_insn "testsi_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm")
(match_operand:SI 1 "general_operand" "in,in,rin"))
@@ -7857,7 +7741,7 @@
(set_attr "pent_pair" "uv,np,uv")])
(define_expand "testsi_ccno_1"
- [(set (reg:CCNO 17)
+ [(set (reg:CCNO FLAGS_REG)
(compare:CCNO
(and:SI (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "nonmemory_operand" ""))
@@ -7866,7 +7750,7 @@
"")
(define_insn "*testhi_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%!*a,r,rm")
(match_operand:HI 1 "general_operand" "n,n,rn"))
(const_int 0)))]
@@ -7879,7 +7763,7 @@
(set_attr "pent_pair" "uv,np,uv")])
(define_expand "testqi_ccz_1"
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand" "")
(match_operand:QI 1 "nonmemory_operand" ""))
(const_int 0)))]
@@ -7887,16 +7771,16 @@
"")
(define_insn "*testqi_1_maybe_si"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:QI
(match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r")
(match_operand:QI 1 "general_operand" "n,n,qn,n"))
(const_int 0)))]
- "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
- && ix86_match_ccmode (insn,
- GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)"
+ "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ && ix86_match_ccmode (insn,
+ GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)"
{
if (which_alternative == 3)
{
@@ -7912,7 +7796,7 @@
(set_attr "pent_pair" "uv,np,uv,np")])
(define_insn "*testqi_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:QI
(match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm")
@@ -7927,7 +7811,7 @@
(set_attr "pent_pair" "uv,np,uv")])
(define_expand "testqi_ext_ccno_0"
- [(set (reg:CCNO 17)
+ [(set (reg:CCNO FLAGS_REG)
(compare:CCNO
(and:SI
(zero_extract:SI
@@ -7940,7 +7824,7 @@
"")
(define_insn "*testqi_ext_0"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:SI
(zero_extract:SI
@@ -7957,7 +7841,7 @@
(set_attr "pent_pair" "np")])
(define_insn "*testqi_ext_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:SI
(zero_extract:SI
@@ -7974,7 +7858,7 @@
(set_attr "mode" "QI")])
(define_insn "*testqi_ext_1_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:SI
(zero_extract:SI
@@ -7990,7 +7874,7 @@
(set_attr "mode" "QI")])
(define_insn "*testqi_ext_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:SI
(zero_extract:SI
@@ -8009,13 +7893,16 @@
;; Combine likes to form bit extractions for some tests. Humor it.
(define_insn "*testqi_ext_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (zero_extract:SI
(match_operand 0 "nonimmediate_operand" "rm")
(match_operand:SI 1 "const_int_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)
+ && INTVAL (operands[1]) > 0
+ && INTVAL (operands[2]) >= 0
+ && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
&& (GET_MODE (operands[0]) == SImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
|| GET_MODE (operands[0]) == HImode
@@ -8023,7 +7910,7 @@
"#")
(define_insn "*testqi_ext_3_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (zero_extract:DI
(match_operand 0 "nonimmediate_operand" "rm")
(match_operand:DI 1 "const_int_operand" "")
@@ -8031,8 +7918,8 @@
(const_int 0)))]
"TARGET_64BIT
&& ix86_match_ccmode (insn, CCNOmode)
- /* The code below cannot deal with constants outside HOST_WIDE_INT. */
- && INTVAL (operands[1]) + INTVAL (operands[2]) < HOST_BITS_PER_WIDE_INT
+ && INTVAL (operands[1]) > 0
+ && INTVAL (operands[2]) >= 0
/* Ensure that resulting mask is zero or sign extended operand. */
&& (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
|| (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
@@ -8087,8 +7974,11 @@
val = gen_lowpart (QImode, val);
}
- mask = ((HOST_WIDE_INT)1 << (pos + len)) - 1;
- mask &= ~(((HOST_WIDE_INT)1 << pos) - 1);
+ if (len == HOST_BITS_PER_WIDE_INT)
+ mask = -1;
+ else
+ mask = ((HOST_WIDE_INT)1 << len) - 1;
+ mask <<= pos;
operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode));
})
@@ -8147,7 +8037,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(and:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "x86_64_szext_general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"ix86_expand_binary_operator (AND, DImode, operands); DONE;")
@@ -8155,7 +8045,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
(and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
(match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
{
switch (get_attr_type (insn))
@@ -8164,14 +8054,14 @@
{
enum machine_mode mode;
- if (GET_CODE (operands[2]) != CONST_INT)
- abort ();
+ gcc_assert (GET_CODE (operands[2]) == CONST_INT);
if (INTVAL (operands[2]) == 0xff)
mode = QImode;
- else if (INTVAL (operands[2]) == 0xffff)
- mode = HImode;
else
- abort ();
+ {
+ gcc_assert (INTVAL (operands[2]) == 0xffff);
+ mode = HImode;
+ }
operands[1] = gen_lowpart (mode, operands[1]);
if (mode == QImode)
@@ -8181,8 +8071,7 @@
}
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
if (get_attr_mode (insn) == MODE_SI)
return "and{l}\t{%k2, %k0|%k0, %k2}";
else
@@ -8194,7 +8083,7 @@
(set_attr "mode" "SI,DI,DI,DI")])
(define_insn "*anddi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re"))
(const_int 0)))
@@ -8203,8 +8092,8 @@
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
&& ix86_binary_operator_ok (AND, DImode, operands)"
"@
- and{l}\t{%k2, %k0|%k0, %k2}
- and{q}\t{%2, %0|%0, %2}
+ and{l}\t{%k2, %k0|%k0, %k2}
+ and{q}\t{%2, %0|%0, %2}
and{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI,DI,DI")])
@@ -8213,7 +8102,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(and:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (AND, SImode, operands); DONE;")
@@ -8221,7 +8110,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r")
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm")
(match_operand:SI 2 "general_operand" "ri,rm,L")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (AND, SImode, operands)"
{
switch (get_attr_type (insn))
@@ -8230,14 +8119,14 @@
{
enum machine_mode mode;
- if (GET_CODE (operands[2]) != CONST_INT)
- abort ();
+ gcc_assert (GET_CODE (operands[2]) == CONST_INT);
if (INTVAL (operands[2]) == 0xff)
mode = QImode;
- else if (INTVAL (operands[2]) == 0xffff)
- mode = HImode;
else
- abort ();
+ {
+ gcc_assert (INTVAL (operands[2]) == 0xffff);
+ mode = HImode;
+ }
operands[1] = gen_lowpart (mode, operands[1]);
if (mode == QImode)
@@ -8247,8 +8136,7 @@
}
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
return "and{l}\t{%2, %0|%0, %2}";
}
}
@@ -8260,7 +8148,7 @@
[(set (match_operand 0 "register_operand" "")
(and (match_dup 0)
(const_int -65536)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"optimize_size || (TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL)"
[(set (strict_low_part (match_dup 1)) (const_int 0))]
"operands[1] = gen_lowpart (HImode, operands[0]);")
@@ -8269,7 +8157,7 @@
[(set (match_operand 0 "ext_register_operand" "")
(and (match_dup 0)
(const_int -256)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
[(set (strict_low_part (match_dup 1)) (const_int 0))]
"operands[1] = gen_lowpart (QImode, operands[0]);")
@@ -8278,7 +8166,7 @@
[(set (match_operand 0 "ext_register_operand" "")
(and (match_dup 0)
(const_int -65281)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(optimize_size || !TARGET_PARTIAL_REG_STALL) && reload_completed"
[(parallel [(set (zero_extract:SI (match_dup 0)
(const_int 8)
@@ -8290,7 +8178,7 @@
(zero_extract:SI (match_dup 0)
(const_int 8)
(const_int 8))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (SImode, operands[0]);")
;; See comment for addsi_1_zext why we do use nonimmediate_operand
@@ -8299,14 +8187,14 @@
(zero_extend:DI
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
"and{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*andsi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "rim,ri"))
(const_int 0)))
@@ -8320,7 +8208,7 @@
;; See comment for addsi_1_zext why we do use nonimmediate_operand
(define_insn "*andsi_2_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))
(const_int 0)))
@@ -8336,7 +8224,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(and:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (AND, HImode, operands); DONE;")
@@ -8344,21 +8232,18 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,qm")
(match_operand:HI 2 "general_operand" "ri,rm,L")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (AND, HImode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_IMOVX:
- if (GET_CODE (operands[2]) != CONST_INT)
- abort ();
- if (INTVAL (operands[2]) == 0xff)
- return "movz{bl|x}\t{%b1, %k0|%k0, %b1}";
- abort ();
+ gcc_assert (GET_CODE (operands[2]) == CONST_INT);
+ gcc_assert (INTVAL (operands[2]) == 0xff);
+ return "movz{bl|x}\t{%b1, %k0|%k0, %b1}";
default:
- if (! rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
return "and{w}\t{%2, %0|%0, %2}";
}
@@ -8368,7 +8253,7 @@
(set_attr "mode" "HI,HI,SI")])
(define_insn "*andhi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "rim,ri"))
(const_int 0)))
@@ -8384,7 +8269,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(and:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (AND, QImode, operands); DONE;")
@@ -8393,7 +8278,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r")
(and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:QI 2 "general_operand" "qi,qmi,ri")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (AND, QImode, operands)"
"@
and{b}\t{%2, %0|%0, %2}
@@ -8406,7 +8291,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
(and:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qi,qmi")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"and{b}\t{%1, %0|%0, %1}"
@@ -8414,7 +8299,7 @@
(set_attr "mode" "QI")])
(define_insn "*andqi_2_maybe_si"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (and:QI
(match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:QI 2 "general_operand" "qim,qi,i"))
@@ -8438,7 +8323,7 @@
(set_attr "mode" "QI,QI,SI")])
(define_insn "*andqi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (and:QI
(match_operand:QI 1 "nonimmediate_operand" "%0,0")
(match_operand:QI 2 "general_operand" "qim,qi"))
@@ -8452,7 +8337,7 @@
(set_attr "mode" "QI")])
(define_insn "*andqi_2_slp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (and:QI
(match_operand:QI 0 "nonimmediate_operand" "+q,qm")
(match_operand:QI 1 "nonimmediate_operand" "qmi,qi"))
@@ -8480,7 +8365,7 @@
(const_int 8)
(const_int 8))
(match_operand 2 "const_int_operand" "n")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
@@ -8491,7 +8376,7 @@
;; often in fp comparisons.
(define_insn "*andqi_ext_0_cc"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(and:SI
(zero_extract:SI
@@ -8526,7 +8411,7 @@
(const_int 8))
(zero_extend:SI
(match_operand:QI 2 "general_operand" "Qm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
"and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
@@ -8544,7 +8429,7 @@
(const_int 8))
(zero_extend:SI
(match_operand 2 "ext_register_operand" "Q"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
@@ -8564,7 +8449,7 @@
(match_operand 2 "ext_register_operand" "Q")
(const_int 8)
(const_int 8))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"and{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
@@ -8580,7 +8465,7 @@
[(set (match_operand 0 "register_operand" "")
(and (match_operand 1 "register_operand" "")
(match_operand 2 "const_int_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& QI_REG_P (operands[0])
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)
@@ -8590,7 +8475,7 @@
(and:SI (zero_extract:SI (match_dup 1)
(const_int 8) (const_int 8))
(match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);
operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
@@ -8601,7 +8486,7 @@
[(set (match_operand 0 "register_operand" "")
(and (match_operand 1 "general_operand" "")
(match_operand 2 "const_int_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ANY_QI_REG_P (operands[0])
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)
@@ -8611,7 +8496,7 @@
[(parallel [(set (strict_low_part (match_dup 0))
(and:QI (match_dup 1)
(match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (QImode, operands[0]);
operands[1] = gen_lowpart (QImode, operands[1]);
operands[2] = gen_lowpart (QImode, operands[2]);")
@@ -8625,7 +8510,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "x86_64_general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"ix86_expand_binary_operator (IOR, DImode, operands); DONE;")
@@ -8633,7 +8518,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rme")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& ix86_binary_operator_ok (IOR, DImode, operands)"
"or{q}\t{%2, %0|%0, %2}"
@@ -8641,7 +8526,7 @@
(set_attr "mode" "DI")])
(define_insn "*iordi_2_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "x86_64_general_operand" "rem,re"))
(const_int 0)))
@@ -8655,7 +8540,7 @@
(set_attr "mode" "DI")])
(define_insn "*iordi_3_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "x86_64_general_operand" "rem"))
(const_int 0)))
@@ -8672,7 +8557,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (IOR, SImode, operands); DONE;")
@@ -8680,7 +8565,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "ri,rmi")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (IOR, SImode, operands)"
"or{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
@@ -8692,7 +8577,7 @@
(zero_extend:DI
(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
"or{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
@@ -8702,14 +8587,14 @@
[(set (match_operand:DI 0 "register_operand" "=rm")
(ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"or{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*iorsi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "rim,ri"))
(const_int 0)))
@@ -8724,7 +8609,7 @@
;; See comment for addsi_1_zext why we do use nonimmediate_operand
;; ??? Special case for immediate operand is missing - it is tricky.
(define_insn "*iorsi_2_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))
(const_int 0)))
@@ -8737,7 +8622,7 @@
(set_attr "mode" "SI")])
(define_insn "*iorsi_2_zext_imm"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand 2 "x86_64_zext_immediate_operand" "Z"))
(const_int 0)))
@@ -8750,7 +8635,7 @@
(set_attr "mode" "SI")])
(define_insn "*iorsi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))
(const_int 0)))
@@ -8765,7 +8650,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (IOR, HImode, operands); DONE;")
@@ -8773,14 +8658,14 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
(ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "rmi,ri")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (IOR, HImode, operands)"
"or{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "HI")])
(define_insn "*iorhi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "rim,ri"))
(const_int 0)))
@@ -8793,7 +8678,7 @@
(set_attr "mode" "HI")])
(define_insn "*iorhi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
(match_operand:HI 2 "general_operand" "rim"))
(const_int 0)))
@@ -8808,7 +8693,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (IOR, QImode, operands); DONE;")
@@ -8817,7 +8702,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (IOR, QImode, operands)"
"@
or{b}\t{%2, %0|%0, %2}
@@ -8830,7 +8715,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m"))
(ior:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qmi,qi")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"or{b}\t{%1, %0|%0, %1}"
@@ -8838,7 +8723,7 @@
(set_attr "mode" "QI")])
(define_insn "*iorqi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
(match_operand:QI 2 "general_operand" "qim,qi"))
(const_int 0)))
@@ -8851,7 +8736,7 @@
(set_attr "mode" "QI")])
(define_insn "*iorqi_2_slp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
(match_operand:QI 1 "general_operand" "qim,qi"))
(const_int 0)))
@@ -8865,7 +8750,7 @@
(set_attr "mode" "QI")])
(define_insn "*iorqi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
(match_operand:QI 2 "general_operand" "qim"))
(const_int 0)))
@@ -8886,7 +8771,7 @@
(const_int 8)
(const_int 8))
(match_operand 2 "const_int_operand" "n")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(!TARGET_PARTIAL_REG_STALL || optimize_size)"
"or{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
@@ -8904,7 +8789,7 @@
(const_int 8))
(zero_extend:SI
(match_operand:QI 2 "general_operand" "Qm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)"
"or{b}\t{%2, %h0|%h0, %2}"
@@ -8923,7 +8808,7 @@
(const_int 8))
(zero_extend:SI
(match_operand 2 "ext_register_operand" "Q"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)"
"or{b}\t{%2, %h0|%h0, %2}"
@@ -8942,7 +8827,7 @@
(zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
(const_int 8)
(const_int 8))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(!TARGET_PARTIAL_REG_STALL || optimize_size)"
"ior{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
@@ -8953,7 +8838,7 @@
[(set (match_operand 0 "register_operand" "")
(ior (match_operand 1 "register_operand" "")
(match_operand 2 "const_int_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& QI_REG_P (operands[0])
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)
@@ -8963,7 +8848,7 @@
(ior:SI (zero_extract:SI (match_dup 1)
(const_int 8) (const_int 8))
(match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);
operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
@@ -8974,7 +8859,7 @@
[(set (match_operand 0 "register_operand" "")
(ior (match_operand 1 "general_operand" "")
(match_operand 2 "const_int_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ANY_QI_REG_P (operands[0])
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)
@@ -8984,7 +8869,7 @@
[(parallel [(set (strict_low_part (match_dup 0))
(ior:QI (match_dup 1)
(match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (QImode, operands[0]);
operands[1] = gen_lowpart (QImode, operands[1]);
operands[2] = gen_lowpart (QImode, operands[2]);")
@@ -8998,7 +8883,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "x86_64_general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"ix86_expand_binary_operator (XOR, DImode, operands); DONE;")
@@ -9006,17 +8891,17 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "x86_64_general_operand" "re,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& ix86_binary_operator_ok (XOR, DImode, operands)"
"@
- xor{q}\t{%2, %0|%0, %2}
+ xor{q}\t{%2, %0|%0, %2}
xor{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "DI,DI")])
(define_insn "*xordi_2_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "x86_64_general_operand" "rem,re"))
(const_int 0)))
@@ -9026,13 +8911,13 @@
&& ix86_match_ccmode (insn, CCNOmode)
&& ix86_binary_operator_ok (XOR, DImode, operands)"
"@
- xor{q}\t{%2, %0|%0, %2}
+ xor{q}\t{%2, %0|%0, %2}
xor{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "DI,DI")])
(define_insn "*xordi_3_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "x86_64_general_operand" "rem"))
(const_int 0)))
@@ -9048,7 +8933,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(xor:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (XOR, SImode, operands); DONE;")
@@ -9056,7 +8941,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "ri,rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (XOR, SImode, operands)"
"xor{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
@@ -9069,7 +8954,7 @@
(zero_extend:DI
(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
"xor{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
@@ -9079,14 +8964,14 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
(match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
"xor{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(define_insn "*xorsi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "rim,ri"))
(const_int 0)))
@@ -9101,7 +8986,7 @@
;; See comment for addsi_1_zext why we do use nonimmediate_operand
;; ??? Special case for immediate operand is missing - it is tricky.
(define_insn "*xorsi_2_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))
(const_int 0)))
@@ -9114,7 +8999,7 @@
(set_attr "mode" "SI")])
(define_insn "*xorsi_2_zext_imm"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand 2 "x86_64_zext_immediate_operand" "Z"))
(const_int 0)))
@@ -9127,7 +9012,7 @@
(set_attr "mode" "SI")])
(define_insn "*xorsi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "general_operand" "rim"))
(const_int 0)))
@@ -9142,7 +9027,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (XOR, HImode, operands); DONE;")
@@ -9150,14 +9035,14 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,m")
(xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "rmi,ri")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (XOR, HImode, operands)"
"xor{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "HI")])
(define_insn "*xorhi_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
(match_operand:HI 2 "general_operand" "rim,ri"))
(const_int 0)))
@@ -9170,7 +9055,7 @@
(set_attr "mode" "HI")])
(define_insn "*xorhi_3"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0")
(match_operand:HI 2 "general_operand" "rim"))
(const_int 0)))
@@ -9185,7 +9070,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (XOR, QImode, operands); DONE;")
@@ -9194,7 +9079,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r")
(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:QI 2 "general_operand" "qmi,qi,ri")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (XOR, QImode, operands)"
"@
xor{b}\t{%2, %0|%0, %2}
@@ -9207,7 +9092,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
(xor:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qi,qmi")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"xor{b}\t{%1, %0|%0, %1}"
@@ -9224,7 +9109,7 @@
(const_int 8)
(const_int 8))
(match_operand 2 "const_int_operand" "n")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(!TARGET_PARTIAL_REG_STALL || optimize_size)"
"xor{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
@@ -9242,7 +9127,7 @@
(const_int 8))
(zero_extend:SI
(match_operand:QI 2 "general_operand" "Qm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)"
"xor{b}\t{%2, %h0|%h0, %2}"
@@ -9261,7 +9146,7 @@
(const_int 8))
(zero_extend:SI
(match_operand 2 "ext_register_operand" "Q"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)"
"xor{b}\t{%2, %h0|%h0, %2}"
@@ -9280,7 +9165,7 @@
(zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
(const_int 8)
(const_int 8))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(!TARGET_PARTIAL_REG_STALL || optimize_size)"
"xor{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
@@ -9288,7 +9173,7 @@
(set_attr "mode" "QI")])
(define_insn "*xorqi_cc_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
(match_operand:QI 2 "general_operand" "qim,qi"))
@@ -9302,7 +9187,7 @@
(set_attr "mode" "QI")])
(define_insn "*xorqi_2_slp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
(match_operand:QI 1 "general_operand" "qim,qi"))
(const_int 0)))
@@ -9316,7 +9201,7 @@
(set_attr "mode" "QI")])
(define_insn "*xorqi_cc_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
(match_operand:QI 2 "general_operand" "qim"))
@@ -9329,7 +9214,7 @@
(set_attr "mode" "QI")])
(define_insn "*xorqi_cc_ext_1"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(xor:SI
(zero_extract:SI
@@ -9350,7 +9235,7 @@
(set_attr "mode" "QI")])
(define_insn "*xorqi_cc_ext_1_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(xor:SI
(zero_extract:SI
@@ -9372,7 +9257,7 @@
(define_expand "xorqi_cc_ext_1"
[(parallel [
- (set (reg:CCNO 17)
+ (set (reg:CCNO FLAGS_REG)
(compare:CCNO
(xor:SI
(zero_extract:SI
@@ -9394,7 +9279,7 @@
[(set (match_operand 0 "register_operand" "")
(xor (match_operand 1 "register_operand" "")
(match_operand 2 "const_int_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& QI_REG_P (operands[0])
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)
@@ -9404,7 +9289,7 @@
(xor:SI (zero_extract:SI (match_dup 1)
(const_int 8) (const_int 8))
(match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);
operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
@@ -9415,7 +9300,7 @@
[(set (match_operand 0 "register_operand" "")
(xor (match_operand 1 "general_operand" "")
(match_operand 2 "const_int_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ANY_QI_REG_P (operands[0])
&& (!TARGET_PARTIAL_REG_STALL || optimize_size)
@@ -9425,24 +9310,61 @@
[(parallel [(set (strict_low_part (match_dup 0))
(xor:QI (match_dup 1)
(match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (QImode, operands[0]);
operands[1] = gen_lowpart (QImode, operands[1]);
operands[2] = gen_lowpart (QImode, operands[2]);")
;; Negation instructions
+(define_expand "negti2"
+ [(parallel [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (neg:TI (match_operand:TI 1 "nonimmediate_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
+ "ix86_expand_unary_operator (NEG, TImode, operands); DONE;")
+
+(define_insn "*negti2_1"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=ro")
+ (neg:TI (match_operand:TI 1 "general_operand" "0")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT
+ && ix86_unary_operator_ok (NEG, TImode, operands)"
+ "#")
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (neg:TI (match_operand:TI 1 "general_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(parallel
+ [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (neg:DI (match_dup 2)) (const_int 0)))
+ (set (match_dup 0) (neg:DI (match_dup 2)))])
+ (parallel
+ [(set (match_dup 1)
+ (plus:DI (plus:DI (ltu:DI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 3))
+ (const_int 0)))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel
+ [(set (match_dup 1)
+ (neg:DI (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_ti (operands+1, 1, operands+2, operands+3);
+ split_ti (operands+0, 1, operands+0, operands+1);")
+
(define_expand "negdi2"
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
(neg:DI (match_operand:DI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"ix86_expand_unary_operator (NEG, DImode, operands); DONE;")
(define_insn "*negdi2_1"
[(set (match_operand:DI 0 "nonimmediate_operand" "=ro")
(neg:DI (match_operand:DI 1 "general_operand" "0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT
&& ix86_unary_operator_ok (NEG, DImode, operands)"
"#")
@@ -9450,29 +9372,29 @@
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(neg:DI (match_operand:DI 1 "general_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && reload_completed"
[(parallel
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (neg:SI (match_dup 2)) (const_int 0)))
(set (match_dup 0) (neg:SI (match_dup 2)))])
(parallel
[(set (match_dup 1)
- (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+ (plus:SI (plus:SI (ltu:SI (reg:CC FLAGS_REG) (const_int 0))
(match_dup 3))
(const_int 0)))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(parallel
[(set (match_dup 1)
(neg:SI (match_dup 1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"split_di (operands+1, 1, operands+2, operands+3);
split_di (operands+0, 1, operands+0, operands+1);")
(define_insn "*negdi2_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(neg:DI (match_operand:DI 1 "nonimmediate_operand" "0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
"neg{q}\t%0"
[(set_attr "type" "negnot")
@@ -9483,7 +9405,7 @@
;; flag being the only useful item.
(define_insn "*negdi2_cmpz_rex64"
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
@@ -9497,14 +9419,14 @@
(define_expand "negsi2"
[(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
(neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"ix86_expand_unary_operator (NEG, SImode, operands); DONE;")
(define_insn "*negsi2_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_unary_operator_ok (NEG, SImode, operands)"
"neg{l}\t%0"
[(set_attr "type" "negnot")
@@ -9516,7 +9438,7 @@
(lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0")
(const_int 32)))
(const_int 32)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
"neg{l}\t%k0"
[(set_attr "type" "negnot")
@@ -9527,7 +9449,7 @@
;; flag being the only useful item.
(define_insn "*negsi2_cmpz"
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
@@ -9538,7 +9460,7 @@
(set_attr "mode" "SI")])
(define_insn "*negsi2_cmpz_zext"
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (lshiftrt:DI
(neg:DI (ashift:DI
(match_operand:DI 1 "register_operand" "0")
@@ -9557,21 +9479,21 @@
(define_expand "neghi2"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_HIMODE_MATH"
"ix86_expand_unary_operator (NEG, HImode, operands); DONE;")
(define_insn "*neghi2_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_unary_operator_ok (NEG, HImode, operands)"
"neg{w}\t%0"
[(set_attr "type" "negnot")
(set_attr "mode" "HI")])
(define_insn "*neghi2_cmpz"
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
@@ -9584,21 +9506,21 @@
(define_expand "negqi2"
[(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "")
(neg:QI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_QIMODE_MATH"
"ix86_expand_unary_operator (NEG, QImode, operands); DONE;")
(define_insn "*negqi2_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_unary_operator_ok (NEG, QImode, operands)"
"neg{b}\t%0"
[(set_attr "type" "negnot")
(set_attr "mode" "QI")])
(define_insn "*negqi2_cmpz"
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
@@ -9611,747 +9533,403 @@
;; Changing of sign for FP values is doable using integer unit too.
(define_expand "negsf2"
- [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ (neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
"TARGET_80387 || TARGET_SSE_MATH"
- "if (TARGET_SSE_MATH)
- {
- /* In case operand is in memory, we will not use SSE. */
- if (memory_operand (operands[0], VOIDmode)
- && rtx_equal_p (operands[0], operands[1]))
- emit_insn (gen_negsf2_memory (operands[0], operands[1]));
- else
- {
- /* Using SSE is tricky, since we need bitwise negation of -0
- in register. */
- rtx reg = gen_reg_rtx (SFmode);
- rtx dest = operands[0];
- rtx imm = gen_lowpart (SFmode, gen_int_mode (0x80000000, SImode));
-
- operands[1] = force_reg (SFmode, operands[1]);
- operands[0] = force_reg (SFmode, operands[0]);
- reg = force_reg (V4SFmode,
- gen_rtx_CONST_VECTOR (V4SFmode,
- gen_rtvec (4, imm, CONST0_RTX (SFmode),
- CONST0_RTX (SFmode),
- CONST0_RTX (SFmode))));
- emit_insn (gen_negsf2_ifs (operands[0], operands[1], reg));
- if (dest != operands[0])
- emit_move_insn (dest, operands[0]);
- }
- DONE;
- }
- ix86_expand_unary_operator (NEG, SFmode, operands); DONE;")
+ "ix86_expand_fp_absneg_operator (NEG, SFmode, operands); DONE;")
-(define_insn "negsf2_memory"
- [(set (match_operand:SF 0 "memory_operand" "=m")
- (neg:SF (match_operand:SF 1 "memory_operand" "0")))
- (clobber (reg:CC 17))]
- "ix86_unary_operator_ok (NEG, SFmode, operands)"
+(define_expand "abssf2"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ (abs:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
+ "TARGET_80387 || TARGET_SSE_MATH"
+ "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;")
+
+(define_insn "*absnegsf2_mixed"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x ,x,f,rm")
+ (match_operator:SF 3 "absneg_operator"
+ [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0,0 ")]))
+ (use (match_operand:V4SF 2 "nonimmediate_operand" "xm ,0,X,X "))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_SSE_MATH && TARGET_MIX_SSE_I387
+ && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
"#")
-(define_insn "negsf2_ifs"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=x#fr,x#fr,f#xr,rm#xf")
- (neg:SF (match_operand:SF 1 "nonimmediate_operand" "0,x#fr,0,0")))
- (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,xm*r,xm*r"))
- (clobber (reg:CC 17))]
- "TARGET_SSE
- && (reload_in_progress || reload_completed
- || (register_operand (operands[0], VOIDmode)
- && register_operand (operands[1], VOIDmode)))"
+(define_insn "*absnegsf2_sse"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,x,rm")
+ (match_operator:SF 3 "absneg_operator"
+ [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0")]))
+ (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,X"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_SSE_MATH
+ && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
"#")
-(define_split
- [(set (match_operand:SF 0 "memory_operand" "")
- (neg:SF (match_operand:SF 1 "memory_operand" "")))
- (use (match_operand:SF 2 "" ""))
- (clobber (reg:CC 17))]
- ""
- [(parallel [(set (match_dup 0)
- (neg:SF (match_dup 1)))
- (clobber (reg:CC 17))])])
-
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (neg:SF (match_operand:SF 1 "register_operand" "")))
- (use (match_operand:V4SF 2 "" ""))
- (clobber (reg:CC 17))]
- "reload_completed && !SSE_REG_P (operands[0])"
- [(parallel [(set (match_dup 0)
- (neg:SF (match_dup 1)))
- (clobber (reg:CC 17))])])
+(define_insn "*absnegsf2_i387"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,rm")
+ (match_operator:SF 3 "absneg_operator"
+ [(match_operand:SF 1 "nonimmediate_operand" "0,0")]))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_80387 && !TARGET_SSE_MATH
+ && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)"
+ "#")
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (neg:SF (match_operand:SF 1 "register_operand" "")))
- (use (match_operand:V4SF 2 "nonimmediate_operand" ""))
- (clobber (reg:CC 17))]
- "reload_completed && SSE_REG_P (operands[0])"
- [(set (match_dup 0)
- (xor:V4SF (match_dup 1)
- (match_dup 2)))]
+(define_expand "copysignsf3"
+ [(match_operand:SF 0 "register_operand" "")
+ (match_operand:SF 1 "nonmemory_operand" "")
+ (match_operand:SF 2 "register_operand" "")]
+ "TARGET_SSE_MATH"
{
- operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
- operands[1] = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
- if (operands_match_p (operands[0], operands[2]))
- {
- rtx tmp;
- tmp = operands[1];
- operands[1] = operands[2];
- operands[2] = tmp;
- }
+ ix86_expand_copysign (operands);
+ DONE;
})
+(define_insn_and_split "copysignsf3_const"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (unspec:SF
+ [(match_operand:V4SF 1 "vector_move_operand" "xmC")
+ (match_operand:SF 2 "register_operand" "0")
+ (match_operand:V4SF 3 "nonimmediate_operand" "xm")]
+ UNSPEC_COPYSIGN))]
+ "TARGET_SSE_MATH"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ ix86_split_copysign_const (operands);
+ DONE;
+})
-;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
-;; because of secondary memory needed to reload from class FLOAT_INT_REGS
-;; to itself.
-(define_insn "*negsf2_if"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f#r,rm#f")
- (neg:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")))
- (clobber (reg:CC 17))]
- "TARGET_80387
- && ix86_unary_operator_ok (NEG, SFmode, operands)"
+(define_insn "copysignsf3_var"
+ [(set (match_operand:SF 0 "register_operand" "=x, x, x, x,x")
+ (unspec:SF
+ [(match_operand:SF 2 "register_operand" " x, 0, 0, x,x")
+ (match_operand:SF 3 "register_operand" " 1, 1, x, 1,x")
+ (match_operand:V4SF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
+ (match_operand:V4SF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
+ UNSPEC_COPYSIGN))
+ (clobber (match_scratch:V4SF 1 "=x, x, x, x,x"))]
+ "TARGET_SSE_MATH"
"#")
(define_split
- [(set (match_operand:SF 0 "fp_register_operand" "")
- (neg:SF (match_operand:SF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 0)
- (neg:SF (match_dup 1)))]
- "")
-
-(define_split
- [(set (match_operand:SF 0 "register_and_not_fp_reg_operand" "")
- (neg:SF (match_operand:SF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC 17))])]
- "operands[1] = gen_int_mode (0x80000000, SImode);
- operands[0] = gen_lowpart (SImode, operands[0]);")
-
-(define_split
- [(set (match_operand 0 "memory_operand" "")
- (neg (match_operand 1 "memory_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))"
- [(parallel [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC 17))])]
+ [(set (match_operand:SF 0 "register_operand" "")
+ (unspec:SF
+ [(match_operand:SF 2 "register_operand" "")
+ (match_operand:SF 3 "register_operand" "")
+ (match_operand:V4SF 4 "" "")
+ (match_operand:V4SF 5 "" "")]
+ UNSPEC_COPYSIGN))
+ (clobber (match_scratch:V4SF 1 ""))]
+ "TARGET_SSE_MATH && reload_completed"
+ [(const_int 0)]
{
- int size = GET_MODE_SIZE (GET_MODE (operands[1]));
-
- if (GET_MODE (operands[1]) == XFmode)
- size = 10;
- operands[0] = adjust_address (operands[0], QImode, size - 1);
- operands[1] = gen_int_mode (0x80, QImode);
+ ix86_split_copysign_var (operands);
+ DONE;
})
(define_expand "negdf2"
- [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
"TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
- "if (TARGET_SSE2 && TARGET_SSE_MATH)
- {
- /* In case operand is in memory, we will not use SSE. */
- if (memory_operand (operands[0], VOIDmode)
- && rtx_equal_p (operands[0], operands[1]))
- emit_insn (gen_negdf2_memory (operands[0], operands[1]));
- else
- {
- /* Using SSE is tricky, since we need bitwise negation of -0
- in register. */
- rtx reg;
-#if HOST_BITS_PER_WIDE_INT >= 64
- rtx imm = gen_int_mode (((HOST_WIDE_INT)1) << 63, DImode);
-#else
- rtx imm = immed_double_const (0, 0x80000000, DImode);
-#endif
- rtx dest = operands[0];
-
- operands[1] = force_reg (DFmode, operands[1]);
- operands[0] = force_reg (DFmode, operands[0]);
- imm = gen_lowpart (DFmode, imm);
- reg = force_reg (V2DFmode,
- gen_rtx_CONST_VECTOR (V2DFmode,
- gen_rtvec (2, imm, CONST0_RTX (DFmode))));
- emit_insn (gen_negdf2_ifs (operands[0], operands[1], reg));
- if (dest != operands[0])
- emit_move_insn (dest, operands[0]);
- }
- DONE;
- }
- ix86_expand_unary_operator (NEG, DFmode, operands); DONE;")
+ "ix86_expand_fp_absneg_operator (NEG, DFmode, operands); DONE;")
-(define_insn "negdf2_memory"
- [(set (match_operand:DF 0 "memory_operand" "=m")
- (neg:DF (match_operand:DF 1 "memory_operand" "0")))
- (clobber (reg:CC 17))]
- "ix86_unary_operator_ok (NEG, DFmode, operands)"
+(define_expand "absdf2"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (abs:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
+ "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;")
+
+(define_insn "*absnegdf2_mixed"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,Y,f,rm")
+ (match_operator:DF 3 "absneg_operator"
+ [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0,0")]))
+ (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,X,X"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
+ && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
"#")
-(define_insn "negdf2_ifs"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,f#Yr,rm#Yf")
- (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0,0")))
- (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r,Ym*r"))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_SSE2
- && (reload_in_progress || reload_completed
- || (register_operand (operands[0], VOIDmode)
- && register_operand (operands[1], VOIDmode)))"
+(define_insn "*absnegdf2_sse"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,Y,rm")
+ (match_operator:DF 3 "absneg_operator"
+ [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ")]))
+ (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,X "))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
"#")
-(define_insn "*negdf2_ifs_rex64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#f,Y#f,fm#Y")
- (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0")))
- (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r"))
- (clobber (reg:CC 17))]
- "TARGET_64BIT && TARGET_SSE2
- && (reload_in_progress || reload_completed
- || (register_operand (operands[0], VOIDmode)
- && register_operand (operands[1], VOIDmode)))"
+(define_insn "*absnegdf2_i387"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,rm")
+ (match_operator:DF 3 "absneg_operator"
+ [(match_operand:DF 1 "nonimmediate_operand" "0,0")]))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
+ && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)"
"#")
-(define_split
- [(set (match_operand:DF 0 "memory_operand" "")
- (neg:DF (match_operand:DF 1 "memory_operand" "")))
- (use (match_operand:V2DF 2 "" ""))
- (clobber (reg:CC 17))]
- ""
- [(parallel [(set (match_dup 0)
- (neg:DF (match_dup 1)))
- (clobber (reg:CC 17))])])
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (neg:DF (match_operand:DF 1 "register_operand" "")))
- (use (match_operand:V2DF 2 "" ""))
- (clobber (reg:CC 17))]
- "reload_completed && !SSE_REG_P (operands[0])
- && (!TARGET_64BIT || FP_REG_P (operands[0]))"
- [(parallel [(set (match_dup 0)
- (neg:DF (match_dup 1)))
- (clobber (reg:CC 17))])])
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (neg:DF (match_operand:DF 1 "register_operand" "")))
- (use (match_operand:V2DF 2 "" ""))
- (clobber (reg:CC 17))]
- "TARGET_64BIT && reload_completed && GENERAL_REG_P (operands[0])"
- [(parallel [(set (match_dup 0)
- (xor:DI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))])]
- "operands[0] = gen_lowpart (DImode, operands[0]);
- operands[1] = gen_lowpart (DImode, operands[1]);
- operands[2] = gen_lowpart (DImode, operands[2]);")
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (neg:DF (match_operand:DF 1 "register_operand" "")))
- (use (match_operand:V2DF 2 "nonimmediate_operand" ""))
- (clobber (reg:CC 17))]
- "reload_completed && SSE_REG_P (operands[0])"
- [(set (match_dup 0)
- (xor:V2DF (match_dup 1)
- (match_dup 2)))]
-{
- operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
- operands[1] = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0);
- /* Avoid possible reformatting on the operands. */
- if (TARGET_SSE_PARTIAL_REGS && !optimize_size)
- emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], operands[0]));
- if (operands_match_p (operands[0], operands[2]))
- {
- rtx tmp;
- tmp = operands[1];
- operands[1] = operands[2];
- operands[2] = tmp;
- }
+(define_expand "copysigndf3"
+ [(match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "nonmemory_operand" "")
+ (match_operand:DF 2 "register_operand" "")]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+{
+ ix86_expand_copysign (operands);
+ DONE;
})
-;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
-;; because of secondary memory needed to reload from class FLOAT_INT_REGS
-;; to itself.
-(define_insn "*negdf2_if"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f#r,rm#f")
- (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,0")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_80387
- && ix86_unary_operator_ok (NEG, DFmode, operands)"
- "#")
+(define_insn_and_split "copysigndf3_const"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (unspec:DF
+ [(match_operand:V2DF 1 "vector_move_operand" "xmC")
+ (match_operand:DF 2 "register_operand" "0")
+ (match_operand:V2DF 3 "nonimmediate_operand" "xm")]
+ UNSPEC_COPYSIGN))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ ix86_split_copysign_const (operands);
+ DONE;
+})
-;; FIXME: We should to allow integer registers here. Problem is that
-;; we need another scratch register to get constant from.
-;; Forcing constant to mem if no register available in peep2 should be
-;; safe even for PIC mode, because of RIP relative addressing.
-(define_insn "*negdf2_if_rex64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,mf")
- (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,0")))
- (clobber (reg:CC 17))]
- "TARGET_64BIT && TARGET_80387
- && ix86_unary_operator_ok (NEG, DFmode, operands)"
+(define_insn "copysigndf3_var"
+ [(set (match_operand:DF 0 "register_operand" "=x, x, x, x,x")
+ (unspec:DF
+ [(match_operand:DF 2 "register_operand" " x, 0, 0, x,x")
+ (match_operand:DF 3 "register_operand" " 1, 1, x, 1,x")
+ (match_operand:V2DF 4 "nonimmediate_operand" " X,xm,xm, 0,0")
+ (match_operand:V2DF 5 "nonimmediate_operand" " 0,xm, 1,xm,1")]
+ UNSPEC_COPYSIGN))
+ (clobber (match_scratch:V2DF 1 "=x, x, x, x,x"))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
"#")
(define_split
- [(set (match_operand:DF 0 "fp_register_operand" "")
- (neg:DF (match_operand:DF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 0)
- (neg:DF (match_dup 1)))]
- "")
-
-(define_split
- [(set (match_operand:DF 0 "register_and_not_fp_reg_operand" "")
- (neg:DF (match_operand:DF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_80387 && reload_completed"
- [(parallel [(set (match_dup 3) (xor:SI (match_dup 3) (match_dup 4)))
- (clobber (reg:CC 17))])]
- "operands[4] = gen_int_mode (0x80000000, SImode);
- split_di (operands+0, 1, operands+2, operands+3);")
+ [(set (match_operand:DF 0 "register_operand" "")
+ (unspec:DF
+ [(match_operand:DF 2 "register_operand" "")
+ (match_operand:DF 3 "register_operand" "")
+ (match_operand:V2DF 4 "" "")
+ (match_operand:V2DF 5 "" "")]
+ UNSPEC_COPYSIGN))
+ (clobber (match_scratch:V2DF 1 ""))]
+ "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
+ [(const_int 0)]
+{
+ ix86_split_copysign_var (operands);
+ DONE;
+})
(define_expand "negxf2"
- [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "")
- (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
- "TARGET_80387"
- "ix86_expand_unary_operator (NEG, XFmode, operands); DONE;")
-
-;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
-;; because of secondary memory needed to reload from class FLOAT_INT_REGS
-;; to itself.
-(define_insn "*negxf2_if"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,rm#f")
- (neg:XF (match_operand:XF 1 "nonimmediate_operand" "0,0")))
- (clobber (reg:CC 17))]
- "TARGET_80387
- && ix86_unary_operator_ok (NEG, XFmode, operands)"
- "#")
-
-(define_split
- [(set (match_operand:XF 0 "fp_register_operand" "")
- (neg:XF (match_operand:XF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 0)
- (neg:XF (match_dup 1)))]
- "")
-
-(define_split
- [(set (match_operand:XF 0 "register_and_not_fp_reg_operand" "")
- (neg:XF (match_operand:XF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC 17))])]
- "operands[1] = GEN_INT (0x8000);
- operands[0] = gen_rtx_REG (SImode,
- true_regnum (operands[0]) + (TARGET_64BIT ? 1 : 2));")
-
-;; Conditionalize these after reload. If they matches before reload, we
-;; lose the clobber and ability to use integer instructions.
-
-(define_insn "*negsf2_1"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (neg:SF (match_operand:SF 1 "register_operand" "0")))]
- "TARGET_80387 && reload_completed"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "SF")
- (set_attr "ppro_uops" "few")])
-
-(define_insn "*negdf2_1"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (match_operand:DF 1 "register_operand" "0")))]
- "TARGET_80387 && reload_completed"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "DF")
- (set_attr "ppro_uops" "few")])
-
-(define_insn "*negextendsfdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))))]
- "TARGET_80387"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "DF")
- (set_attr "ppro_uops" "few")])
-
-(define_insn "*negxf2_1"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (neg:XF (match_operand:XF 1 "register_operand" "0")))]
- "TARGET_80387 && reload_completed"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "XF")
- (set_attr "ppro_uops" "few")])
-
-(define_insn "*negextenddfxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (neg:XF (float_extend:XF
- (match_operand:DF 1 "register_operand" "0"))))]
+ [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
"TARGET_80387"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "XF")
- (set_attr "ppro_uops" "few")])
+ "ix86_expand_fp_absneg_operator (NEG, XFmode, operands); DONE;")
-(define_insn "*negextendsfxf2"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (neg:XF (float_extend:XF
- (match_operand:SF 1 "register_operand" "0"))))]
+(define_expand "absxf2"
+ [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ (abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
"TARGET_80387"
- "fchs"
- [(set_attr "type" "fsgn")
- (set_attr "mode" "XF")
- (set_attr "ppro_uops" "few")])
-
-;; Absolute value instructions
-
-(define_expand "abssf2"
- [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (neg:SF (match_operand:SF 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
- "TARGET_80387 || TARGET_SSE_MATH"
- "if (TARGET_SSE_MATH)
- {
- /* In case operand is in memory, we will not use SSE. */
- if (memory_operand (operands[0], VOIDmode)
- && rtx_equal_p (operands[0], operands[1]))
- emit_insn (gen_abssf2_memory (operands[0], operands[1]));
- else
- {
- /* Using SSE is tricky, since we need bitwise negation of -0
- in register. */
- rtx reg = gen_reg_rtx (V4SFmode);
- rtx dest = operands[0];
- rtx imm;
-
- operands[1] = force_reg (SFmode, operands[1]);
- operands[0] = force_reg (SFmode, operands[0]);
- imm = gen_lowpart (SFmode, gen_int_mode(~0x80000000, SImode));
- reg = force_reg (V4SFmode,
- gen_rtx_CONST_VECTOR (V4SFmode,
- gen_rtvec (4, imm, CONST0_RTX (SFmode),
- CONST0_RTX (SFmode),
- CONST0_RTX (SFmode))));
- emit_insn (gen_abssf2_ifs (operands[0], operands[1], reg));
- if (dest != operands[0])
- emit_move_insn (dest, operands[0]);
- }
- DONE;
- }
- ix86_expand_unary_operator (ABS, SFmode, operands); DONE;")
-
-(define_insn "abssf2_memory"
- [(set (match_operand:SF 0 "memory_operand" "=m")
- (abs:SF (match_operand:SF 1 "memory_operand" "0")))
- (clobber (reg:CC 17))]
- "ix86_unary_operator_ok (ABS, SFmode, operands)"
- "#")
-
-(define_insn "abssf2_ifs"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=x#fr,x#fr,f#xr,rm#xf")
- (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0,x#fr,0,0")))
- (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,xm*r,xm*r"))
- (clobber (reg:CC 17))]
- "TARGET_SSE
- && (reload_in_progress || reload_completed
- || (register_operand (operands[0], VOIDmode)
- && register_operand (operands[1], VOIDmode)))"
+ "ix86_expand_fp_absneg_operator (ABS, XFmode, operands); DONE;")
+
+(define_insn "*absnegxf2_i387"
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,?rm")
+ (match_operator:XF 3 "absneg_operator"
+ [(match_operand:XF 1 "nonimmediate_operand" "0,0")]))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_80387
+ && ix86_unary_operator_ok (GET_CODE (operands[3]), XFmode, operands)"
"#")
-(define_split
- [(set (match_operand:SF 0 "memory_operand" "")
- (abs:SF (match_operand:SF 1 "memory_operand" "")))
- (use (match_operand:V4SF 2 "" ""))
- (clobber (reg:CC 17))]
- ""
- [(parallel [(set (match_dup 0)
- (abs:SF (match_dup 1)))
- (clobber (reg:CC 17))])])
+;; Splitters for fp abs and neg.
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (abs:SF (match_operand:SF 1 "register_operand" "")))
- (use (match_operand:V4SF 2 "" ""))
- (clobber (reg:CC 17))]
- "reload_completed && !SSE_REG_P (operands[0])"
- [(parallel [(set (match_dup 0)
- (abs:SF (match_dup 1)))
- (clobber (reg:CC 17))])])
+ [(set (match_operand 0 "fp_register_operand" "")
+ (match_operator 1 "absneg_operator" [(match_dup 0)]))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed"
+ [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))])
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (abs:SF (match_operand:SF 1 "register_operand" "")))
- (use (match_operand:V4SF 2 "nonimmediate_operand" ""))
- (clobber (reg:CC 17))]
+ [(set (match_operand 0 "register_operand" "")
+ (match_operator 3 "absneg_operator"
+ [(match_operand 1 "register_operand" "")]))
+ (use (match_operand 2 "nonimmediate_operand" ""))
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed && SSE_REG_P (operands[0])"
- [(set (match_dup 0)
- (and:V4SF (match_dup 1)
- (match_dup 2)))]
+ [(set (match_dup 0) (match_dup 3))]
{
- operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
- operands[1] = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+ enum machine_mode mode = GET_MODE (operands[0]);
+ enum machine_mode vmode = GET_MODE (operands[2]);
+ rtx tmp;
+
+ operands[0] = simplify_gen_subreg (vmode, operands[0], mode, 0);
+ operands[1] = simplify_gen_subreg (vmode, operands[1], mode, 0);
if (operands_match_p (operands[0], operands[2]))
{
- rtx tmp;
tmp = operands[1];
operands[1] = operands[2];
operands[2] = tmp;
}
+ if (GET_CODE (operands[3]) == ABS)
+ tmp = gen_rtx_AND (vmode, operands[1], operands[2]);
+ else
+ tmp = gen_rtx_XOR (vmode, operands[1], operands[2]);
+ operands[3] = tmp;
})
-;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
-;; because of secondary memory needed to reload from class FLOAT_INT_REGS
-;; to itself.
-(define_insn "*abssf2_if"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f#r,rm#f")
- (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && ix86_unary_operator_ok (ABS, SFmode, operands)"
- "#")
-
(define_split
- [(set (match_operand:SF 0 "fp_register_operand" "")
- (abs:SF (match_operand:SF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 0)
- (abs:SF (match_dup 1)))]
- "")
-
-(define_split
- [(set (match_operand:SF 0 "register_and_not_fp_reg_operand" "")
- (abs:SF (match_operand:SF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC 17))])]
- "operands[1] = gen_int_mode (~0x80000000, SImode);
- operands[0] = gen_lowpart (SImode, operands[0]);")
+ [(set (match_operand:SF 0 "register_operand" "")
+ (match_operator:SF 1 "absneg_operator" [(match_dup 0)]))
+ (use (match_operand:V4SF 2 "" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ rtx tmp;
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ if (GET_CODE (operands[1]) == ABS)
+ {
+ tmp = gen_int_mode (0x7fffffff, SImode);
+ tmp = gen_rtx_AND (SImode, operands[0], tmp);
+ }
+ else
+ {
+ tmp = gen_int_mode (0x80000000, SImode);
+ tmp = gen_rtx_XOR (SImode, operands[0], tmp);
+ }
+ operands[1] = tmp;
+})
(define_split
- [(set (match_operand 0 "memory_operand" "")
- (abs (match_operand 1 "memory_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))"
- [(parallel [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC 17))])]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operator:DF 1 "absneg_operator" [(match_dup 0)]))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC FLAGS_REG))])]
{
- int size = GET_MODE_SIZE (GET_MODE (operands[1]));
-
- if (GET_MODE (operands[1]) == XFmode)
- size = 10;
- operands[0] = adjust_address (operands[0], QImode, size - 1);
- operands[1] = gen_int_mode (~0x80, QImode);
-})
+ rtx tmp;
+ if (TARGET_64BIT)
+ {
+ tmp = gen_lowpart (DImode, operands[0]);
+ tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63));
+ operands[0] = tmp;
-(define_expand "absdf2"
- [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (neg:DF (match_operand:DF 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
- "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
- "if (TARGET_SSE2 && TARGET_SSE_MATH)
- {
- /* In case operand is in memory, we will not use SSE. */
- if (memory_operand (operands[0], VOIDmode)
- && rtx_equal_p (operands[0], operands[1]))
- emit_insn (gen_absdf2_memory (operands[0], operands[1]));
- else
+ if (GET_CODE (operands[1]) == ABS)
+ tmp = const0_rtx;
+ else
+ tmp = gen_rtx_NOT (DImode, tmp);
+ }
+ else
+ {
+ operands[0] = gen_highpart (SImode, operands[0]);
+ if (GET_CODE (operands[1]) == ABS)
{
- /* Using SSE is tricky, since we need bitwise negation of -0
- in register. */
- rtx reg = gen_reg_rtx (V2DFmode);
-#if HOST_BITS_PER_WIDE_INT >= 64
- rtx imm = gen_int_mode (~(((HOST_WIDE_INT)1) << 63), DImode);
-#else
- rtx imm = immed_double_const (~0, ~0x80000000, DImode);
-#endif
- rtx dest = operands[0];
-
- operands[1] = force_reg (DFmode, operands[1]);
- operands[0] = force_reg (DFmode, operands[0]);
-
- /* Produce LONG_DOUBLE with the proper immediate argument. */
- imm = gen_lowpart (DFmode, imm);
- reg = force_reg (V2DFmode,
- gen_rtx_CONST_VECTOR (V2DFmode,
- gen_rtvec (2, imm, CONST0_RTX (DFmode))));
- emit_insn (gen_absdf2_ifs (operands[0], operands[1], reg));
- if (dest != operands[0])
- emit_move_insn (dest, operands[0]);
+ tmp = gen_int_mode (0x7fffffff, SImode);
+ tmp = gen_rtx_AND (SImode, operands[0], tmp);
}
- DONE;
- }
- ix86_expand_unary_operator (ABS, DFmode, operands); DONE;")
-
-(define_insn "absdf2_memory"
- [(set (match_operand:DF 0 "memory_operand" "=m")
- (abs:DF (match_operand:DF 1 "memory_operand" "0")))
- (clobber (reg:CC 17))]
- "ix86_unary_operator_ok (ABS, DFmode, operands)"
- "#")
-
-(define_insn "absdf2_ifs"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,mf#Yr,mr#Yf")
- (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0,0")))
- (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r,Ym*r"))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_SSE2
- && (reload_in_progress || reload_completed
- || (register_operand (operands[0], VOIDmode)
- && register_operand (operands[1], VOIDmode)))"
- "#")
-
-(define_insn "*absdf2_ifs_rex64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,mf#Yr")
- (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0")))
- (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r"))
- (clobber (reg:CC 17))]
- "TARGET_64BIT && TARGET_SSE2
- && (reload_in_progress || reload_completed
- || (register_operand (operands[0], VOIDmode)
- && register_operand (operands[1], VOIDmode)))"
- "#")
+ else
+ {
+ tmp = gen_int_mode (0x80000000, SImode);
+ tmp = gen_rtx_XOR (SImode, operands[0], tmp);
+ }
+ }
+ operands[1] = tmp;
+})
(define_split
- [(set (match_operand:DF 0 "memory_operand" "")
- (abs:DF (match_operand:DF 1 "memory_operand" "")))
- (use (match_operand:V2DF 2 "" ""))
- (clobber (reg:CC 17))]
- ""
- [(parallel [(set (match_dup 0)
- (abs:DF (match_dup 1)))
- (clobber (reg:CC 17))])])
+ [(set (match_operand:XF 0 "register_operand" "")
+ (match_operator:XF 1 "absneg_operator" [(match_dup 0)]))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ rtx tmp;
+ operands[0] = gen_rtx_REG (SImode,
+ true_regnum (operands[0])
+ + (TARGET_64BIT ? 1 : 2));
+ if (GET_CODE (operands[1]) == ABS)
+ {
+ tmp = GEN_INT (0x7fff);
+ tmp = gen_rtx_AND (SImode, operands[0], tmp);
+ }
+ else
+ {
+ tmp = GEN_INT (0x8000);
+ tmp = gen_rtx_XOR (SImode, operands[0], tmp);
+ }
+ operands[1] = tmp;
+})
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (abs:DF (match_operand:DF 1 "register_operand" "")))
- (use (match_operand:V2DF 2 "" ""))
- (clobber (reg:CC 17))]
- "reload_completed && !SSE_REG_P (operands[0])"
- [(parallel [(set (match_dup 0)
- (abs:DF (match_dup 1)))
- (clobber (reg:CC 17))])])
+ [(set (match_operand 0 "memory_operand" "")
+ (match_operator 1 "absneg_operator" [(match_dup 0)]))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ int size = mode == XFmode ? 10 : GET_MODE_SIZE (mode);
+ rtx tmp;
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (abs:DF (match_operand:DF 1 "register_operand" "")))
- (use (match_operand:V2DF 2 "nonimmediate_operand" ""))
- (clobber (reg:CC 17))]
- "reload_completed && SSE_REG_P (operands[0])"
- [(set (match_dup 0)
- (and:V2DF (match_dup 1)
- (match_dup 2)))]
-{
- operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
- operands[1] = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0);
- /* Avoid possible reformatting on the operands. */
- if (TARGET_SSE_PARTIAL_REGS && !optimize_size)
- emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], operands[0]));
- if (operands_match_p (operands[0], operands[2]))
+ operands[0] = adjust_address (operands[0], QImode, size - 1);
+ if (GET_CODE (operands[1]) == ABS)
{
- rtx tmp;
- tmp = operands[1];
- operands[1] = operands[2];
- operands[2] = tmp;
+ tmp = gen_int_mode (0x7f, QImode);
+ tmp = gen_rtx_AND (QImode, operands[0], tmp);
}
+ else
+ {
+ tmp = gen_int_mode (0x80, QImode);
+ tmp = gen_rtx_XOR (QImode, operands[0], tmp);
+ }
+ operands[1] = tmp;
})
+;; Conditionalize these after reload. If they match before reload, we
+;; lose the clobber and ability to use integer instructions.
-;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
-;; because of secondary memory needed to reload from class FLOAT_INT_REGS
-;; to itself.
-(define_insn "*absdf2_if"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f#r,rm#f")
- (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,0")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_80387
- && ix86_unary_operator_ok (ABS, DFmode, operands)"
- "#")
-
-;; FIXME: We should to allow integer registers here. Problem is that
-;; we need another scratch register to get constant from.
-;; Forcing constant to mem if no register available in peep2 should be
-;; safe even for PIC mode, because of RIP relative addressing.
-(define_insn "*absdf2_if_rex64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,mf")
- (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,0")))
- (clobber (reg:CC 17))]
- "TARGET_64BIT && TARGET_80387
- && ix86_unary_operator_ok (ABS, DFmode, operands)"
- "#")
-
-(define_split
- [(set (match_operand:DF 0 "fp_register_operand" "")
- (abs:DF (match_operand:DF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 0)
- (abs:DF (match_dup 1)))]
- "")
+(define_insn "*negsf2_1"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "register_operand" "0")))]
+ "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
+ "fchs"
+ [(set_attr "type" "fsgn")
+ (set_attr "mode" "SF")])
-(define_split
- [(set (match_operand:DF 0 "register_and_not_fp_reg_operand" "")
- (abs:DF (match_operand:DF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_80387 && reload_completed"
- [(parallel [(set (match_dup 3) (and:SI (match_dup 3) (match_dup 4)))
- (clobber (reg:CC 17))])]
- "operands[4] = gen_int_mode (~0x80000000, SImode);
- split_di (operands+0, 1, operands+2, operands+3);")
+(define_insn "*negdf2_1"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "register_operand" "0")))]
+ "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
+ "fchs"
+ [(set_attr "type" "fsgn")
+ (set_attr "mode" "DF")])
-(define_expand "absxf2"
- [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "")
- (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))])]
+(define_insn "*negxf2_1"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (neg:XF (match_operand:XF 1 "register_operand" "0")))]
"TARGET_80387"
- "ix86_expand_unary_operator (ABS, XFmode, operands); DONE;")
-
-;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
-;; because of secondary memory needed to reload from class FLOAT_INT_REGS
-;; to itself.
-(define_insn "*absxf2_if"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,rm#f")
- (abs:XF (match_operand:XF 1 "nonimmediate_operand" "0,0")))
- (clobber (reg:CC 17))]
- "TARGET_80387
- && ix86_unary_operator_ok (ABS, XFmode, operands)"
- "#")
-
-(define_split
- [(set (match_operand:XF 0 "fp_register_operand" "")
- (abs:XF (match_operand:XF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 0)
- (abs:XF (match_dup 1)))]
- "")
-
-(define_split
- [(set (match_operand:XF 0 "register_and_not_fp_reg_operand" "")
- (abs:XF (match_operand:XF 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed"
- [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC 17))])]
- "operands[1] = GEN_INT (~0x8000);
- operands[0] = gen_rtx_REG (SImode,
- true_regnum (operands[0]) + (TARGET_64BIT ? 1 : 2));")
+ "fchs"
+ [(set_attr "type" "fsgn")
+ (set_attr "mode" "XF")])
(define_insn "*abssf2_1"
[(set (match_operand:SF 0 "register_operand" "=f")
(abs:SF (match_operand:SF 1 "register_operand" "0")))]
- "TARGET_80387 && reload_completed"
+ "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)"
"fabs"
[(set_attr "type" "fsgn")
(set_attr "mode" "SF")])
@@ -10359,24 +9937,51 @@
(define_insn "*absdf2_1"
[(set (match_operand:DF 0 "register_operand" "=f")
(abs:DF (match_operand:DF 1 "register_operand" "0")))]
- "TARGET_80387 && reload_completed"
+ "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))"
"fabs"
[(set_attr "type" "fsgn")
(set_attr "mode" "DF")])
-(define_insn "*absextendsfdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))))]
+(define_insn "*absxf2_1"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (abs:XF (match_operand:XF 1 "register_operand" "0")))]
"TARGET_80387"
"fabs"
[(set_attr "type" "fsgn")
(set_attr "mode" "DF")])
-(define_insn "*absxf2_1"
+(define_insn "*negextendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (float_extend:DF
+ (match_operand:SF 1 "register_operand" "0"))))]
+ "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
+ "fchs"
+ [(set_attr "type" "fsgn")
+ (set_attr "mode" "DF")])
+
+(define_insn "*negextenddfxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
- (abs:XF (match_operand:XF 1 "register_operand" "0")))]
- "TARGET_80387 && reload_completed"
+ (neg:XF (float_extend:XF
+ (match_operand:DF 1 "register_operand" "0"))))]
+ "TARGET_80387"
+ "fchs"
+ [(set_attr "type" "fsgn")
+ (set_attr "mode" "XF")])
+
+(define_insn "*negextendsfxf2"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (neg:XF (float_extend:XF
+ (match_operand:SF 1 "register_operand" "0"))))]
+ "TARGET_80387"
+ "fchs"
+ [(set_attr "type" "fsgn")
+ (set_attr "mode" "XF")])
+
+(define_insn "*absextendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (float_extend:DF
+ (match_operand:SF 1 "register_operand" "0"))))]
+ "TARGET_80387 && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)"
"fabs"
[(set_attr "type" "fsgn")
(set_attr "mode" "DF")])
@@ -10416,7 +10021,7 @@
(set_attr "mode" "DI")])
(define_insn "*one_cmpldi2_2_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
@@ -10467,7 +10072,7 @@
(set_attr "mode" "SI")])
(define_insn "*one_cmplsi2_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
@@ -10495,7 +10100,7 @@
;; ??? Currently never generated - xor is used instead.
(define_insn "*one_cmplsi2_2_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (not:SI (match_operand:SI 1 "register_operand" "0"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
@@ -10536,7 +10141,7 @@
(set_attr "mode" "HI")])
(define_insn "*one_cmplhi2_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (not:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
@@ -10580,7 +10185,7 @@
(set_attr "mode" "QI,SI")])
(define_insn "*one_cmplqi2_2"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare (not:QI (match_operand:QI 1 "nonimmediate_operand" "0"))
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
@@ -10630,42 +10235,116 @@
;; shift pair, instead using moves and sign extension for counts greater
;; than 31.
-(define_expand "ashldi3"
- [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "")
- (ashift:DI (match_operand:DI 1 "shiftdi_operand" "")
+(define_expand "ashlti3"
+ [(parallel [(set (match_operand:TI 0 "register_operand" "")
+ (ashift:TI (match_operand:TI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))])]
- ""
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
{
- if (!TARGET_64BIT && TARGET_CMOVE && ! immediate_operand (operands[2], QImode))
+ if (! immediate_operand (operands[2], QImode))
{
- emit_insn (gen_ashldi3_1 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_ashlti3_1 (operands[0], operands[1], operands[2]));
DONE;
}
- ix86_expand_binary_operator (ASHIFT, DImode, operands);
+ ix86_expand_binary_operator (ASHIFT, TImode, operands);
DONE;
})
+(define_insn "ashlti3_1"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (ashift:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "c")))
+ (clobber (match_scratch:DI 3 "=&r"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_insn "*ashlti3_2"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (ashift:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "O")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashift:TI (match_operand:TI 1 "nonmemory_operand" "")
+ (match_operand:QI 2 "register_operand" "")))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashl (operands, operands[3], TImode); DONE;")
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashift:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "immediate_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashl (operands, NULL_RTX, TImode); DONE;")
+
+(define_insn "x86_64_shld"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
+ (ior:DI (ashift:DI (match_dup 0)
+ (match_operand:QI 2 "nonmemory_operand" "J,c"))
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "r,r")
+ (minus:QI (const_int 64) (match_dup 2)))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "@
+ shld{q}\t{%2, %1, %0|%0, %1, %2}
+ shld{q}\t{%s2%1, %0|%0, %1, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")
+ (set_attr "athlon_decode" "vector")])
+
+(define_expand "x86_64_shift_adj"
+ [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
+ (const_int 64))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "")
+ (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
+ (match_operand:DI 1 "register_operand" "")
+ (match_dup 0)))
+ (set (match_dup 1)
+ (if_then_else:DI (ne (reg:CCZ FLAGS_REG) (const_int 0))
+ (match_operand:DI 3 "register_operand" "r")
+ (match_dup 1)))]
+ "TARGET_64BIT"
+ "")
+
+(define_expand "ashldi3"
+ [(set (match_operand:DI 0 "shiftdi_operand" "")
+ (ashift:DI (match_operand:DI 1 "ashldi_input_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
+ ""
+ "ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;")
+
(define_insn "*ashldi3_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
- (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,r")
+ (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,l")
(match_operand:QI 2 "nonmemory_operand" "cJ,M")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
- if (!rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
return "add{q}\t{%0, %0|%0, %0}";
case TYPE_LEA:
- if (GET_CODE (operands[2]) != CONST_INT
- || (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 3)
- abort ();
+ gcc_assert (GET_CODE (operands[2]) == CONST_INT);
+ gcc_assert ((unsigned HOST_WIDE_INT) INTVAL (operands[2]) <= 3);
operands[1] = gen_rtx_MULT (DImode, operands[1],
GEN_INT (1 << INTVAL (operands[2])));
return "lea{q}\t{%a1, %0|%0, %a1}";
@@ -10673,8 +10352,7 @@
default:
if (REG_P (operands[2]))
return "sal{q}\t{%b2, %0|%0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{q}\t%0";
else
@@ -10696,9 +10374,9 @@
;; Convert lea to the lea pattern to avoid flags dependency.
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (ashift:DI (match_operand:DI 1 "index_register_operand" "")
(match_operand:QI 2 "immediate_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(set (match_dup 0)
@@ -10710,7 +10388,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashldi3_cmp_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "immediate_operand" "e"))
@@ -10718,20 +10396,23 @@
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(ashift:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, DImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
return "add{q}\t{%0, %0|%0, %0}";
default:
if (REG_P (operands[2]))
return "sal{q}\t{%b2, %0|%0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{q}\t%0";
else
@@ -10748,43 +10429,79 @@
(const_string "ishift")))
(set_attr "mode" "DI")])
-(define_insn "ashldi3_1"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ashift:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "Jc")))
- (clobber (match_scratch:SI 3 "=&r"))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_CMOVE"
- "#"
- [(set_attr "type" "multi")])
+(define_insn "*ashldi3_cconly_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "e"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, DImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{q}\t{%0, %0|%0, %0}";
-(define_insn "*ashldi3_2"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ashift:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "Jc")))
- (clobber (reg:CC 17))]
+ default:
+ if (REG_P (operands[2]))
+ return "sal{q}\t{%b2, %0|%0, %b2}";
+ else if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_size))
+ return "sal{q}\t%0";
+ else
+ return "sal{q}\t{%2, %0|%0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 0 "register_operand" ""))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set_attr "mode" "DI")])
+
+(define_insn "*ashldi3_1"
+ [(set (match_operand:DI 0 "register_operand" "=&r,r")
+ (ashift:DI (match_operand:DI 1 "reg_or_pm1_operand" "n,0")
+ (match_operand:QI 2 "nonmemory_operand" "Jc,Jc")))
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
"#"
[(set_attr "type" "multi")])
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (ashift:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (match_scratch:SI 3 ""))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_CMOVE && reload_completed"
+;; By default we don't ask for a scratch register, because when DImode
+;; values are manipulated, registers are already at a premium. But if
+;; we have one handy, we won't turn it away.
+(define_peephole2
+ [(match_scratch:SI 3 "r")
+ (parallel [(set (match_operand:DI 0 "register_operand" "")
+ (ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])
+ (match_dup 3)]
+ "!TARGET_64BIT && TARGET_CMOVE"
[(const_int 0)]
- "ix86_split_ashldi (operands, operands[3]); DONE;")
+ "ix86_split_ashl (operands, operands[3], DImode); DONE;")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (ashift:DI (match_operand:DI 1 "nonmemory_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && reload_completed"
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
+ ? flow2_completed : reload_completed)"
[(const_int 0)]
- "ix86_split_ashldi (operands, NULL_RTX); DONE;")
+ "ix86_split_ashl (operands, NULL_RTX, DImode); DONE;")
(define_insn "x86_shld_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
@@ -10792,7 +10509,7 @@
(match_operand:QI 2 "nonmemory_operand" "I,c"))
(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
(minus:QI (const_int 32) (match_dup 2)))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"@
shld{l}\t{%2, %1, %0|%0, %1, %2}
@@ -10801,20 +10518,19 @@
(set_attr "prefix_0f" "1")
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
- (set_attr "athlon_decode" "vector")
- (set_attr "ppro_uops" "few")])
+ (set_attr "athlon_decode" "vector")])
(define_expand "x86_shift_adj_1"
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (and:QI (match_operand:QI 2 "register_operand" "")
(const_int 32))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "")
- (if_then_else:SI (ne (reg:CCZ 17) (const_int 0))
+ (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
(match_operand:SI 1 "register_operand" "")
(match_dup 0)))
(set (match_dup 1)
- (if_then_else:SI (ne (reg:CCZ 17) (const_int 0))
+ (if_then_else:SI (ne (reg:CCZ FLAGS_REG) (const_int 0))
(match_operand:SI 3 "register_operand" "r")
(match_dup 1)))]
"TARGET_CMOVE"
@@ -10840,7 +10556,7 @@
JUMP_LABEL (tmp) = label;
emit_move_insn (operands[0], operands[1]);
- emit_move_insn (operands[1], const0_rtx);
+ ix86_expand_clear (operands[1]);
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -10852,24 +10568,22 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (ASHIFT, SImode, operands); DONE;")
(define_insn "*ashlsi3_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r")
+ (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,l")
(match_operand:QI 2 "nonmemory_operand" "cI,M")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFT, SImode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
- if (!rtx_equal_p (operands[0], operands[1]))
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
+ gcc_assert (rtx_equal_p (operands[0], operands[1]));
return "add{l}\t{%0, %0|%0, %0}";
case TYPE_LEA:
@@ -10878,8 +10592,7 @@
default:
if (REG_P (operands[2]))
return "sal{l}\t{%b2, %0|%0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{l}\t%0";
else
@@ -10903,15 +10616,21 @@
[(set (match_operand 0 "register_operand" "")
(ashift (match_operand 1 "index_register_operand" "")
(match_operand:QI 2 "const_int_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4"
[(const_int 0)]
{
rtx pat;
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (Pmode, operands[1]);
+ enum machine_mode mode = GET_MODE (operands[0]);
+
+ if (GET_MODE_SIZE (mode) < 4)
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ if (mode != Pmode)
+ operands[1] = gen_lowpart (Pmode, operands[1]);
operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
+
pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
if (Pmode != SImode)
pat = gen_rtx_SUBREG (SImode, pat, 0);
@@ -10924,13 +10643,13 @@
[(set (match_operand 0 "register_operand" "")
(ashift (match_operand 1 "register_operand" "")
(match_operand:QI 2 "const_int_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(const_int 0)]
{
rtx pat, clob;
- emit_move_insn (operands[1], operands[0]);
+ emit_move_insn (operands[0], operands[1]);
pat = gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_ASHIFT (GET_MODE (operands[0]),
operands[0], operands[2]));
@@ -10941,16 +10660,15 @@
(define_insn "*ashlsi3_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,r")
+ (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,l")
(match_operand:QI 2 "nonmemory_operand" "cI,M"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
return "add{l}\t{%k0, %k0|%k0, %k0}";
case TYPE_LEA:
@@ -10959,8 +10677,7 @@
default:
if (REG_P (operands[2]))
return "sal{l}\t{%b2, %k0|%k0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{l}\t%k0";
else
@@ -10983,7 +10700,7 @@
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (ashift (match_operand 1 "register_operand" "")
(match_operand:QI 2 "const_int_operand" ""))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(set (match_dup 0) (zero_extend:DI
@@ -10998,28 +10715,72 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashlsi3_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(ashift:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{l}\t{%0, %0|%0, %0}";
+
+ default:
+ if (REG_P (operands[2]))
+ return "sal{l}\t{%b2, %0|%0, %b2}";
+ else if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_size))
+ return "sal{l}\t%0";
+ else
+ return "sal{l}\t{%2, %0|%0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 0 "register_operand" ""))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashlsi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
return "add{l}\t{%0, %0|%0, %0}";
default:
if (REG_P (operands[2]))
return "sal{l}\t{%b2, %0|%0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{l}\t%0";
else
@@ -11037,28 +10798,31 @@
(set_attr "mode" "SI")])
(define_insn "*ashlsi3_cmp_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashift:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
return "add{l}\t{%k0, %k0|%k0, %k0}";
default:
if (REG_P (operands[2]))
return "sal{l}\t{%b2, %k0|%k0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{l}\t%k0";
else
@@ -11078,15 +10842,15 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (ASHIFT, HImode, operands); DONE;")
(define_insn "*ashlhi3_1_lea"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
- (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r")
+ (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l")
(match_operand:QI 2 "nonmemory_operand" "cI,M")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (ASHIFT, HImode, operands)"
{
@@ -11095,15 +10859,13 @@
case TYPE_LEA:
return "#";
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
return "add{w}\t{%0, %0|%0, %0}";
default:
if (REG_P (operands[2]))
return "sal{w}\t{%b2, %0|%0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{w}\t%0";
else
@@ -11126,22 +10888,20 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (ASHIFT, HImode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
return "add{w}\t{%0, %0|%0, %0}";
default:
if (REG_P (operands[2]))
return "sal{w}\t{%b2, %0|%0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{w}\t%0";
else
@@ -11162,28 +10922,72 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashlhi3_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashift:HI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, HImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
return "add{w}\t{%0, %0|%0, %0}";
default:
if (REG_P (operands[2]))
return "sal{w}\t{%b2, %0|%0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_size))
+ return "sal{w}\t%0";
+ else
+ return "sal{w}\t{%2, %0|%0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 0 "register_operand" ""))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set_attr "mode" "HI")])
+
+(define_insn "*ashlhi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{w}\t{%0, %0|%0, %0}";
+
+ default:
+ if (REG_P (operands[2]))
+ return "sal{w}\t{%b2, %0|%0, %b2}";
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{w}\t%0";
else
@@ -11204,7 +11008,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (ASHIFT, QImode, operands); DONE;")
@@ -11212,9 +11016,9 @@
(define_insn "*ashlqi3_1_lea"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,r")
- (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,r")
+ (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l")
(match_operand:QI 2 "nonmemory_operand" "cI,cI,M")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (ASHIFT, QImode, operands)"
{
@@ -11223,8 +11027,7 @@
case TYPE_LEA:
return "#";
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
return "add{l}\t{%k0, %k0|%k0, %k0}";
else
@@ -11238,8 +11041,7 @@
else
return "sal{b}\t{%b2, %0|%0, %b2}";
}
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
{
if (get_attr_mode (insn) == MODE_SI)
@@ -11272,15 +11074,14 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r")
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "cI,cI")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_PARTIAL_REG_STALL
&& ix86_binary_operator_ok (ASHIFT, QImode, operands)"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
if (REG_P (operands[1]) && !ANY_QI_REG_P (operands[1]))
return "add{l}\t{%k0, %k0|%k0, %k0}";
else
@@ -11294,8 +11095,7 @@
else
return "sal{b}\t{%b2, %0|%0, %b2}";
}
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
{
if (get_attr_mode (insn) == MODE_SI)
@@ -11326,28 +11126,72 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashlqi3_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashift:QI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFT, QImode, operands)"
+ && ix86_binary_operator_ok (ASHIFT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
{
switch (get_attr_type (insn))
{
case TYPE_ALU:
- if (operands[2] != const1_rtx)
- abort ();
+ gcc_assert (operands[2] == const1_rtx);
return "add{b}\t{%0, %0|%0, %0}";
default:
if (REG_P (operands[2]))
return "sal{b}\t{%b2, %0|%0, %b2}";
- else if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1
+ else if (operands[2] == const1_rtx
+ && (TARGET_SHIFT1 || optimize_size))
+ return "sal{b}\t%0";
+ else
+ return "sal{b}\t{%2, %0|%0, %2}";
+ }
+}
+ [(set (attr "type")
+ (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+ (const_int 0))
+ (match_operand 0 "register_operand" ""))
+ (match_operand 2 "const1_operand" ""))
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
+ (set_attr "mode" "QI")])
+
+(define_insn "*ashlqi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL
+ || (operands[2] == const1_rtx
+ && (TARGET_SHIFT1
+ || TARGET_DOUBLE_WITH_ADD)))"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{b}\t{%0, %0|%0, %0}";
+
+ default:
+ if (REG_P (operands[2]))
+ return "sal{b}\t{%b2, %0|%0, %b2}";
+ else if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_size))
return "sal{b}\t%0";
else
@@ -11366,28 +11210,90 @@
;; See comment above `ashldi3' about how this works.
-(define_expand "ashrdi3"
- [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "")
- (ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
+(define_expand "ashrti3"
+ [(parallel [(set (match_operand:TI 0 "register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))])]
- ""
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
{
- if (!TARGET_64BIT && TARGET_CMOVE && ! immediate_operand (operands[2], QImode))
+ if (! immediate_operand (operands[2], QImode))
{
- emit_insn (gen_ashrdi3_1 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_ashrti3_1 (operands[0], operands[1], operands[2]));
DONE;
}
- ix86_expand_binary_operator (ASHIFTRT, DImode, operands);
+ ix86_expand_binary_operator (ASHIFTRT, TImode, operands);
DONE;
})
-(define_insn "ashrdi3_63_rex64"
+(define_insn "ashrti3_1"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "c")))
+ (clobber (match_scratch:DI 3 "=&r"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_insn "*ashrti3_2"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "O")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "register_operand" "")))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashr (operands, operands[3], TImode); DONE;")
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "immediate_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_ashr (operands, NULL_RTX, TImode); DONE;")
+
+(define_insn "x86_64_shrd"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m,r*m")
+ (ior:DI (ashiftrt:DI (match_dup 0)
+ (match_operand:QI 2 "nonmemory_operand" "J,c"))
+ (ashift:DI (match_operand:DI 1 "register_operand" "r,r")
+ (minus:QI (const_int 64) (match_dup 2)))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "@
+ shrd{q}\t{%2, %1, %0|%0, %1, %2}
+ shrd{q}\t{%s2%1, %0|%0, %1, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")
+ (set_attr "athlon_decode" "vector")])
+
+(define_expand "ashrdi3"
+ [(set (match_operand:DI 0 "shiftdi_operand" "")
+ (ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
+ ""
+ "ix86_expand_binary_operator (ASHIFTRT, DImode, operands); DONE;")
+
+(define_insn "*ashrdi3_63_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm")
(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0")
(match_operand:DI 2 "const_int_operand" "i,i")))
- (clobber (reg:CC 17))]
- "TARGET_64BIT && INTVAL (operands[2]) == 63 && (TARGET_USE_CLTD || optimize_size)
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && INTVAL (operands[2]) == 63
+ && (TARGET_USE_CLTD || optimize_size)
&& ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
"@
{cqto|cqo}
@@ -11402,7 +11308,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"sar{q}\t%0"
@@ -11416,7 +11322,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "J,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
"@
sar{q}\t{%2, %0|%0, %2}
@@ -11428,7 +11334,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashrdi3_one_bit_cmp_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -11445,11 +11351,25 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrdi3_one_bit_cconly_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+ "sar{q}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashrdi3_cmp_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const_int_operand" "n"))
@@ -11457,49 +11377,60 @@
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(ashiftrt:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "DI")])
+(define_insn "*ashrdi3_cconly_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_int_operand" "n"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "sar{q}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "DI")])
-(define_insn "ashrdi3_1"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "Jc")))
- (clobber (match_scratch:SI 3 "=&r"))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_CMOVE"
- "#"
- [(set_attr "type" "multi")])
-
-(define_insn "*ashrdi3_2"
+(define_insn "*ashrdi3_1"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "Jc")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
"#"
[(set_attr "type" "multi")])
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (match_scratch:SI 3 ""))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_CMOVE && reload_completed"
+;; By default we don't ask for a scratch register, because when DImode
+;; values are manipulated, registers are already at a premium. But if
+;; we have one handy, we won't turn it away.
+(define_peephole2
+ [(match_scratch:SI 3 "r")
+ (parallel [(set (match_operand:DI 0 "register_operand" "")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])
+ (match_dup 3)]
+ "!TARGET_64BIT && TARGET_CMOVE"
[(const_int 0)]
- "ix86_split_ashrdi (operands, operands[3]); DONE;")
+ "ix86_split_ashr (operands, operands[3], DImode); DONE;")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && reload_completed"
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
+ ? flow2_completed : reload_completed)"
[(const_int 0)]
- "ix86_split_ashrdi (operands, NULL_RTX); DONE;")
+ "ix86_split_ashr (operands, NULL_RTX, DImode); DONE;")
(define_insn "x86_shrd_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "+r*m,r*m")
@@ -11507,7 +11438,7 @@
(match_operand:QI 2 "nonmemory_operand" "I,c"))
(ashift:SI (match_operand:SI 1 "register_operand" "r,r")
(minus:QI (const_int 32) (match_dup 2)))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"@
shrd{l}\t{%2, %1, %0|%0, %1, %2}
@@ -11515,7 +11446,6 @@
[(set_attr "type" "ishift")
(set_attr "prefix_0f" "1")
(set_attr "pent_pair" "np")
- (set_attr "ppro_uops" "few")
(set_attr "mode" "SI")])
(define_expand "x86_shift_adj_3"
@@ -11550,7 +11480,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm")
(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0")
(match_operand:SI 2 "const_int_operand" "i,i")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"INTVAL (operands[2]) == 31 && (TARGET_USE_CLTD || optimize_size)
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"@
@@ -11566,7 +11496,7 @@
[(set (match_operand:DI 0 "register_operand" "=*d,r")
(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0")
(match_operand:SI 2 "const_int_operand" "i,i"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && (TARGET_USE_CLTD || optimize_size)
&& INTVAL (operands[2]) == 31
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
@@ -11583,7 +11513,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (ASHIFTRT, SImode, operands); DONE;")
@@ -11591,7 +11521,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"sar{l}\t%0"
@@ -11605,7 +11535,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:QI 2 "const1_operand" ""))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"sar{l}\t%k0"
@@ -11616,7 +11546,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"@
sar{l}\t{%2, %0|%0, %2}
@@ -11628,7 +11558,7 @@
[(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"@
sar{l}\t{%2, %k0|%k0, %2}
@@ -11640,7 +11570,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashrsi3_one_bit_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -11657,8 +11587,22 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrsi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ "sar{l}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
(define_insn "*ashrsi3_one_bit_cmp_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -11676,29 +11620,48 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashrsi3_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(ashiftrt:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "sar{l}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "SI")])
+
+(define_insn "*ashrsi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "SI")])
(define_insn "*ashrsi3_cmp_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "SI")])
@@ -11707,7 +11670,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (ASHIFTRT, HImode, operands); DONE;")
@@ -11715,7 +11678,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"sar{w}\t%0"
@@ -11729,7 +11692,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
"@
sar{w}\t{%2, %0|%0, %2}
@@ -11741,7 +11704,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashrhi3_one_bit_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -11758,19 +11721,50 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrhi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
+ "sar{w}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashrhi3_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashiftrt:HI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "sar{w}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "HI")])
+
+(define_insn "*ashrhi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "HI")])
@@ -11779,7 +11773,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (ASHIFTRT, QImode, operands); DONE;")
@@ -11787,7 +11781,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"sar{b}\t%0"
@@ -11801,7 +11795,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
(ashiftrt:QI (match_dup 0)
(match_operand:QI 1 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
&& (! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (TARGET_SHIFT1 || optimize_size)"
@@ -11816,7 +11810,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
"@
sar{b}\t{%2, %0|%0, %2}
@@ -11828,7 +11822,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
(ashiftrt:QI (match_dup 0)
(match_operand:QI 1 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
@@ -11841,7 +11835,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashrqi3_one_bit_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "I"))
@@ -11858,48 +11852,125 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrqi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
+ "sar{b}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*ashrqi3_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashiftrt:QI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "sar{b}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "QI")])
+
+(define_insn "*ashrqi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"sar{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "QI")])
+
;; Logical shift instructions
;; See comment above `ashldi3' about how this works.
-(define_expand "lshrdi3"
- [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
+(define_expand "lshrti3"
+ [(parallel [(set (match_operand:TI 0 "register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))])]
- ""
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
{
- if (!TARGET_64BIT && TARGET_CMOVE && ! immediate_operand (operands[2], QImode))
+ if (! immediate_operand (operands[2], QImode))
{
- emit_insn (gen_lshrdi3_1 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_lshrti3_1 (operands[0], operands[1], operands[2]));
DONE;
}
- ix86_expand_binary_operator (LSHIFTRT, DImode, operands);
+ ix86_expand_binary_operator (LSHIFTRT, TImode, operands);
DONE;
})
+(define_insn "lshrti3_1"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "c")))
+ (clobber (match_scratch:DI 3 "=&r"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_insn "*lshrti3_2"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:QI 2 "immediate_operand" "O")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ [(set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "register_operand" "")))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_lshr (operands, operands[3], TImode); DONE;")
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:QI 2 "immediate_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && reload_completed"
+ [(const_int 0)]
+ "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;")
+
+(define_expand "lshrdi3"
+ [(set (match_operand:DI 0 "shiftdi_operand" "")
+ (lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
+ ""
+ "ix86_expand_binary_operator (LSHIFTRT, DImode, operands); DONE;")
+
(define_insn "*lshrdi3_1_one_bit_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"shr{q}\t%0"
@@ -11913,7 +11984,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "J,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"@
shr{q}\t{%2, %0|%0, %2}
@@ -11925,7 +11996,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*lshrdi3_cmp_one_bit_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -11942,11 +12013,25 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrdi3_cconly_one_bit_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{q}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*lshrdi3_cmp_rex64"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const_int_operand" "e"))
@@ -11954,54 +12039,66 @@
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(lshiftrt:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "DI")])
-(define_insn "lshrdi3_1"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "Jc")))
- (clobber (match_scratch:SI 3 "=&r"))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_CMOVE"
- "#"
- [(set_attr "type" "multi")])
+(define_insn "*lshrdi3_cconly_rex64"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_int_operand" "e"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=r"))]
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "shr{q}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "DI")])
-(define_insn "*lshrdi3_2"
+(define_insn "*lshrdi3_1"
[(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "Jc")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
"#"
[(set_attr "type" "multi")])
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (match_scratch:SI 3 ""))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_CMOVE && reload_completed"
+;; By default we don't ask for a scratch register, because when DImode
+;; values are manipulated, registers are already at a premium. But if
+;; we have one handy, we won't turn it away.
+(define_peephole2
+ [(match_scratch:SI 3 "r")
+ (parallel [(set (match_operand:DI 0 "register_operand" "")
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])
+ (match_dup 3)]
+ "!TARGET_64BIT && TARGET_CMOVE"
[(const_int 0)]
- "ix86_split_lshrdi (operands, operands[3]); DONE;")
+ "ix86_split_lshr (operands, operands[3], DImode); DONE;")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && reload_completed"
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
+ ? flow2_completed : reload_completed)"
[(const_int 0)]
- "ix86_split_lshrdi (operands, NULL_RTX); DONE;")
+ "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;")
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (LSHIFTRT, SImode, operands); DONE;")
@@ -12009,7 +12106,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"shr{l}\t%0"
@@ -12023,7 +12120,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"shr{l}\t%k0"
@@ -12034,7 +12131,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"@
shr{l}\t{%2, %0|%0, %2}
@@ -12047,7 +12144,7 @@
(zero_extend:DI
(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"@
shr{l}\t{%2, %k0|%k0, %2}
@@ -12059,7 +12156,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*lshrsi3_one_bit_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -12076,8 +12173,22 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrsi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{l}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
(define_insn "*lshrsi3_cmp_one_bit_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -12095,29 +12206,48 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*lshrsi3_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(lshiftrt:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "shr{l}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "SI")])
+
+(define_insn "*lshrsi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "SI")])
(define_insn "*lshrsi3_cmp_zext"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "SI")])
@@ -12126,7 +12256,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (LSHIFTRT, HImode, operands); DONE;")
@@ -12134,7 +12264,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"shr{w}\t%0"
@@ -12148,7 +12278,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"@
shr{w}\t{%2, %0|%0, %2}
@@ -12160,7 +12290,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*lshrhi3_one_bit_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -12177,19 +12307,50 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrhi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{w}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*lshrhi3_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(lshiftrt:HI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "shr{w}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "HI")])
+
+(define_insn "*lshrhi3_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:HI 0 "=r"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "HI")])
@@ -12198,7 +12359,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (LSHIFTRT, QImode, operands); DONE;")
@@ -12206,7 +12367,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"shr{b}\t%0"
@@ -12220,7 +12381,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
(lshiftrt:QI (match_dup 0)
(match_operand:QI 1 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (TARGET_SHIFT1 || optimize_size)"
"shr{b}\t%0"
@@ -12234,7 +12395,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
"@
shr{b}\t{%2, %0|%0, %2}
@@ -12246,7 +12407,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
(lshiftrt:QI (match_dup 0)
(match_operand:QI 1 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
@@ -12259,7 +12420,7 @@
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*lshrqi2_one_bit_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" ""))
@@ -12276,19 +12437,50 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrqi2_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const1_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && (TARGET_SHIFT1 || optimize_size)
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
+ "shr{b}\t%0"
+ [(set_attr "type" "ishift")
+ (set_attr "length" "2")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
(define_insn "*lshrqi2_cmp"
- [(set (reg 17)
+ [(set (reg FLAGS_REG)
(compare
(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
- (match_operand:QI 2 "const_int_1_31_operand" "I"))
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
(const_int 0)))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(lshiftrt:QI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
+ "shr{b}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ishift")
+ (set_attr "mode" "QI")])
+
+(define_insn "*lshrqi2_cconly"
+ [(set (reg FLAGS_REG)
+ (compare
+ (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I"))
+ (const_int 0)))
+ (clobber (match_scratch:QI 0 "=q"))]
+ "ix86_match_ccmode (insn, CCGOCmode)
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
+ && (optimize_size
+ || !TARGET_PARTIAL_FLAG_REG_STALL)"
"shr{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "ishift")
(set_attr "mode" "QI")])
@@ -12296,18 +12488,54 @@
;; Rotate instructions
(define_expand "rotldi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "")
+ [(set (match_operand:DI 0 "shiftdi_operand" "")
+ (rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_64BIT"
- "ix86_expand_binary_operator (ROTATE, DImode, operands); DONE;")
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+{
+ if (TARGET_64BIT)
+ {
+ ix86_expand_binary_operator (ROTATE, DImode, operands);
+ DONE;
+ }
+ if (!const_1_to_31_operand (operands[2], VOIDmode))
+ FAIL;
+ emit_insn (gen_ix86_rotldi3 (operands[0], operands[1], operands[2]));
+ DONE;
+})
+;; Implement rotation using two double-precision shift instructions
+;; and a scratch register.
+(define_insn_and_split "ix86_rotldi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (rotate:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I")))
+ (clobber (reg:CC FLAGS_REG))
+ (clobber (match_scratch:SI 3 "=&r"))]
+ "!TARGET_64BIT"
+ ""
+ "&& reload_completed"
+ [(set (match_dup 3) (match_dup 4))
+ (parallel
+ [(set (match_dup 4)
+ (ior:SI (ashift:SI (match_dup 4) (match_dup 2))
+ (lshiftrt:SI (match_dup 5)
+ (minus:QI (const_int 32) (match_dup 2)))))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel
+ [(set (match_dup 5)
+ (ior:SI (ashift:SI (match_dup 5) (match_dup 2))
+ (lshiftrt:SI (match_dup 3)
+ (minus:QI (const_int 32) (match_dup 2)))))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_di (operands, 1, operands + 4, operands + 5);")
+
(define_insn "*rotlsi3_1_one_bit_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"rol{q}\t%0"
@@ -12321,7 +12549,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
(rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "e,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)"
"@
rol{q}\t{%2, %0|%0, %2}
@@ -12333,7 +12561,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (ROTATE, SImode, operands); DONE;")
@@ -12341,7 +12569,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATE, SImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"rol{l}\t%0"
@@ -12356,7 +12584,7 @@
(zero_extend:DI
(rotate:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:QI 2 "const1_operand" ""))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"rol{l}\t%k0"
@@ -12367,7 +12595,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATE, SImode, operands)"
"@
rol{l}\t{%2, %0|%0, %2}
@@ -12380,7 +12608,7 @@
(zero_extend:DI
(rotate:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)"
"@
rol{l}\t{%2, %k0|%k0, %2}
@@ -12392,7 +12620,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (ROTATE, HImode, operands); DONE;")
@@ -12400,7 +12628,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATE, HImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"rol{w}\t%0"
@@ -12414,7 +12642,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATE, HImode, operands)"
"@
rol{w}\t{%2, %0|%0, %2}
@@ -12426,7 +12654,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;")
@@ -12434,7 +12662,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
(rotate:QI (match_dup 0)
(match_operand:QI 1 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (TARGET_SHIFT1 || optimize_size)"
"rol{b}\t%0"
@@ -12448,7 +12676,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATE, QImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"rol{b}\t%0"
@@ -12462,7 +12690,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
(rotate:QI (match_dup 0)
(match_operand:QI 1 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
@@ -12475,7 +12703,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATE, QImode, operands)"
"@
rol{b}\t{%2, %0|%0, %2}
@@ -12484,18 +12712,54 @@
(set_attr "mode" "QI")])
(define_expand "rotrdi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "TARGET_64BIT"
- "ix86_expand_binary_operator (ROTATERT, DImode, operands); DONE;")
+ [(set (match_operand:DI 0 "shiftdi_operand" "")
+ (rotate:DI (match_operand:DI 1 "shiftdi_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+{
+ if (TARGET_64BIT)
+ {
+ ix86_expand_binary_operator (ROTATERT, DImode, operands);
+ DONE;
+ }
+ if (!const_1_to_31_operand (operands[2], VOIDmode))
+ FAIL;
+ emit_insn (gen_ix86_rotrdi3 (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+;; Implement rotation using two double-precision shift instructions
+;; and a scratch register.
+(define_insn_and_split "ix86_rotrdi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (rotatert:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:QI 2 "const_1_to_31_operand" "I")))
+ (clobber (reg:CC FLAGS_REG))
+ (clobber (match_scratch:SI 3 "=&r"))]
+ "!TARGET_64BIT"
+ ""
+ "&& reload_completed"
+ [(set (match_dup 3) (match_dup 4))
+ (parallel
+ [(set (match_dup 4)
+ (ior:SI (ashiftrt:SI (match_dup 4) (match_dup 2))
+ (ashift:SI (match_dup 5)
+ (minus:QI (const_int 32) (match_dup 2)))))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel
+ [(set (match_dup 5)
+ (ior:SI (ashiftrt:SI (match_dup 5) (match_dup 2))
+ (ashift:SI (match_dup 3)
+ (minus:QI (const_int 32) (match_dup 2)))))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_di (operands, 1, operands + 4, operands + 5);")
(define_insn "*rotrdi3_1_one_bit_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"ror{q}\t%0"
@@ -12509,7 +12773,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
(rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "J,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)"
"@
ror{q}\t{%2, %0|%0, %2}
@@ -12521,7 +12785,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"ix86_expand_binary_operator (ROTATERT, SImode, operands); DONE;")
@@ -12529,7 +12793,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATERT, SImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"ror{l}\t%0"
@@ -12544,7 +12808,7 @@
(zero_extend:DI
(rotatert:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:QI 2 "const1_operand" ""))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"ror{l}\t%k0"
@@ -12558,7 +12822,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATERT, SImode, operands)"
"@
ror{l}\t{%2, %0|%0, %2}
@@ -12571,7 +12835,7 @@
(zero_extend:DI
(rotatert:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)"
"@
ror{l}\t{%2, %k0|%k0, %2}
@@ -12583,7 +12847,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_HIMODE_MATH"
"ix86_expand_binary_operator (ROTATERT, HImode, operands); DONE;")
@@ -12591,7 +12855,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATERT, HImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"ror{w}\t%0"
@@ -12605,7 +12869,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATERT, HImode, operands)"
"@
ror{w}\t{%2, %0|%0, %2}
@@ -12617,7 +12881,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (ROTATERT, QImode, operands); DONE;")
@@ -12625,7 +12889,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATERT, QImode, operands)
&& (TARGET_SHIFT1 || optimize_size)"
"ror{b}\t%0"
@@ -12639,7 +12903,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
(rotatert:QI (match_dup 0)
(match_operand:QI 1 "const1_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (TARGET_SHIFT1 || optimize_size)"
"ror{b}\t%0"
@@ -12653,7 +12917,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ROTATERT, QImode, operands)"
"@
ror{b}\t{%2, %0|%0, %2}
@@ -12665,7 +12929,7 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
(rotatert:QI (match_dup 0)
(match_operand:QI 1 "nonmemory_operand" "I,c")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
@@ -12679,8 +12943,8 @@
(define_expand "extv"
[(set (match_operand:SI 0 "register_operand" "")
(sign_extract:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "immediate_operand" "")
- (match_operand:SI 3 "immediate_operand" "")))]
+ (match_operand:SI 2 "const8_operand" "")
+ (match_operand:SI 3 "const8_operand" "")))]
""
{
/* Handle extractions from %ah et al. */
@@ -12689,15 +12953,15 @@
/* From mips.md: extract_bit_field doesn't verify that our source
matches the predicate, so check it again here. */
- if (! register_operand (operands[1], VOIDmode))
+ if (! ext_register_operand (operands[1], VOIDmode))
FAIL;
})
(define_expand "extzv"
[(set (match_operand:SI 0 "register_operand" "")
(zero_extract:SI (match_operand 1 "ext_register_operand" "")
- (match_operand:SI 2 "immediate_operand" "")
- (match_operand:SI 3 "immediate_operand" "")))]
+ (match_operand:SI 2 "const8_operand" "")
+ (match_operand:SI 3 "const8_operand" "")))]
""
{
/* Handle extractions from %ah et al. */
@@ -12706,24 +12970,24 @@
/* From mips.md: extract_bit_field doesn't verify that our source
matches the predicate, so check it again here. */
- if (! register_operand (operands[1], VOIDmode))
+ if (! ext_register_operand (operands[1], VOIDmode))
FAIL;
})
(define_expand "insv"
[(set (zero_extract (match_operand 0 "ext_register_operand" "")
- (match_operand 1 "immediate_operand" "")
- (match_operand 2 "immediate_operand" ""))
+ (match_operand 1 "const8_operand" "")
+ (match_operand 2 "const8_operand" ""))
(match_operand 3 "register_operand" ""))]
""
{
- /* Handle extractions from %ah et al. */
+ /* Handle insertions to %ah et al. */
if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8)
FAIL;
/* From mips.md: insert_bit_field doesn't verify that our source
matches the predicate, so check it again here. */
- if (! register_operand (operands[0], VOIDmode))
+ if (! ext_register_operand (operands[0], VOIDmode))
FAIL;
if (TARGET_64BIT)
@@ -12735,6 +12999,146 @@
})
;; %%% bts, btr, btc, bt.
+;; In general these instructions are *slow* when applied to memory,
+;; since they enforce atomic operation. When applied to registers,
+;; it depends on the cpu implementation. They're never faster than
+;; the corresponding and/ior/xor operations, so with 32-bit there's
+;; no point. But in 64-bit, we can't hold the relevant immediates
+;; within the instruction itself, so operating on bits in the high
+;; 32-bits of a register becomes easier.
+;;
+;; These are slow on Nocona, but fast on Athlon64. We do require the use
+;; of btrq and btcq for corner cases of post-reload expansion of absdf and
+;; negdf respectively, so they can never be disabled entirely.
+
+(define_insn "*btsq"
+ [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
+ (const_int 1)
+ (match_operand:DI 1 "const_0_to_63_operand" ""))
+ (const_int 1))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
+ "bts{q} %1,%0"
+ [(set_attr "type" "alu1")])
+
+(define_insn "*btrq"
+ [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
+ (const_int 1)
+ (match_operand:DI 1 "const_0_to_63_operand" ""))
+ (const_int 0))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
+ "btr{q} %1,%0"
+ [(set_attr "type" "alu1")])
+
+(define_insn "*btcq"
+ [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
+ (const_int 1)
+ (match_operand:DI 1 "const_0_to_63_operand" ""))
+ (not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
+ "btc{q} %1,%0"
+ [(set_attr "type" "alu1")])
+
+;; Allow Nocona to avoid these instructions if a register is available.
+
+(define_peephole2
+ [(match_scratch:DI 2 "r")
+ (parallel [(set (zero_extract:DI
+ (match_operand:DI 0 "register_operand" "")
+ (const_int 1)
+ (match_operand:DI 1 "const_0_to_63_operand" ""))
+ (const_int 1))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT && !TARGET_USE_BT"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
+ rtx op1;
+
+ if (HOST_BITS_PER_WIDE_INT >= 64)
+ lo = (HOST_WIDE_INT)1 << i, hi = 0;
+ else if (i < HOST_BITS_PER_WIDE_INT)
+ lo = (HOST_WIDE_INT)1 << i, hi = 0;
+ else
+ lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
+
+ op1 = immed_double_const (lo, hi, DImode);
+ if (i >= 31)
+ {
+ emit_move_insn (operands[2], op1);
+ op1 = operands[2];
+ }
+
+ emit_insn (gen_iordi3 (operands[0], operands[0], op1));
+ DONE;
+})
+
+(define_peephole2
+ [(match_scratch:DI 2 "r")
+ (parallel [(set (zero_extract:DI
+ (match_operand:DI 0 "register_operand" "")
+ (const_int 1)
+ (match_operand:DI 1 "const_0_to_63_operand" ""))
+ (const_int 0))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT && !TARGET_USE_BT"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
+ rtx op1;
+
+ if (HOST_BITS_PER_WIDE_INT >= 64)
+ lo = (HOST_WIDE_INT)1 << i, hi = 0;
+ else if (i < HOST_BITS_PER_WIDE_INT)
+ lo = (HOST_WIDE_INT)1 << i, hi = 0;
+ else
+ lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
+
+ op1 = immed_double_const (~lo, ~hi, DImode);
+ if (i >= 32)
+ {
+ emit_move_insn (operands[2], op1);
+ op1 = operands[2];
+ }
+
+ emit_insn (gen_anddi3 (operands[0], operands[0], op1));
+ DONE;
+})
+
+(define_peephole2
+ [(match_scratch:DI 2 "r")
+ (parallel [(set (zero_extract:DI
+ (match_operand:DI 0 "register_operand" "")
+ (const_int 1)
+ (match_operand:DI 1 "const_0_to_63_operand" ""))
+ (not:DI (zero_extract:DI
+ (match_dup 0) (const_int 1) (match_dup 1))))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT && !TARGET_USE_BT"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT i = INTVAL (operands[1]), hi, lo;
+ rtx op1;
+
+ if (HOST_BITS_PER_WIDE_INT >= 64)
+ lo = (HOST_WIDE_INT)1 << i, hi = 0;
+ else if (i < HOST_BITS_PER_WIDE_INT)
+ lo = (HOST_WIDE_INT)1 << i, hi = 0;
+ else
+ lo = 0, hi = (HOST_WIDE_INT)1 << (i - HOST_BITS_PER_WIDE_INT);
+
+ op1 = immed_double_const (lo, hi, DImode);
+ if (i >= 31)
+ {
+ emit_move_insn (operands[2], op1);
+ op1 = operands[2];
+ }
+
+ emit_insn (gen_xordi3 (operands[0], operands[0], op1));
+ DONE;
+})
;; Store-flag instructions.
@@ -12747,125 +13151,125 @@
(define_expand "seq"
[(set (match_operand:QI 0 "register_operand" "")
- (eq:QI (reg:CC 17) (const_int 0)))]
+ (eq:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
(define_expand "sne"
[(set (match_operand:QI 0 "register_operand" "")
- (ne:QI (reg:CC 17) (const_int 0)))]
+ (ne:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
(define_expand "sgt"
[(set (match_operand:QI 0 "register_operand" "")
- (gt:QI (reg:CC 17) (const_int 0)))]
+ (gt:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
(define_expand "sgtu"
[(set (match_operand:QI 0 "register_operand" "")
- (gtu:QI (reg:CC 17) (const_int 0)))]
+ (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
(define_expand "slt"
[(set (match_operand:QI 0 "register_operand" "")
- (lt:QI (reg:CC 17) (const_int 0)))]
+ (lt:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
(define_expand "sltu"
[(set (match_operand:QI 0 "register_operand" "")
- (ltu:QI (reg:CC 17) (const_int 0)))]
+ (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
(define_expand "sge"
[(set (match_operand:QI 0 "register_operand" "")
- (ge:QI (reg:CC 17) (const_int 0)))]
+ (ge:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
(define_expand "sgeu"
[(set (match_operand:QI 0 "register_operand" "")
- (geu:QI (reg:CC 17) (const_int 0)))]
+ (geu:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
(define_expand "sle"
[(set (match_operand:QI 0 "register_operand" "")
- (le:QI (reg:CC 17) (const_int 0)))]
+ (le:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
(define_expand "sleu"
[(set (match_operand:QI 0 "register_operand" "")
- (leu:QI (reg:CC 17) (const_int 0)))]
+ (leu:QI (reg:CC FLAGS_REG) (const_int 0)))]
""
"if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
(define_expand "sunordered"
[(set (match_operand:QI 0 "register_operand" "")
- (unordered:QI (reg:CC 17) (const_int 0)))]
+ (unordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
(define_expand "sordered"
[(set (match_operand:QI 0 "register_operand" "")
- (ordered:QI (reg:CC 17) (const_int 0)))]
+ (ordered:QI (reg:CC FLAGS_REG) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
(define_expand "suneq"
[(set (match_operand:QI 0 "register_operand" "")
- (uneq:QI (reg:CC 17) (const_int 0)))]
+ (uneq:QI (reg:CC FLAGS_REG) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
(define_expand "sunge"
[(set (match_operand:QI 0 "register_operand" "")
- (unge:QI (reg:CC 17) (const_int 0)))]
+ (unge:QI (reg:CC FLAGS_REG) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
(define_expand "sungt"
[(set (match_operand:QI 0 "register_operand" "")
- (ungt:QI (reg:CC 17) (const_int 0)))]
+ (ungt:QI (reg:CC FLAGS_REG) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
(define_expand "sunle"
[(set (match_operand:QI 0 "register_operand" "")
- (unle:QI (reg:CC 17) (const_int 0)))]
+ (unle:QI (reg:CC FLAGS_REG) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
(define_expand "sunlt"
[(set (match_operand:QI 0 "register_operand" "")
- (unlt:QI (reg:CC 17) (const_int 0)))]
+ (unlt:QI (reg:CC FLAGS_REG) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
(define_expand "sltgt"
[(set (match_operand:QI 0 "register_operand" "")
- (ltgt:QI (reg:CC 17) (const_int 0)))]
+ (ltgt:QI (reg:CC FLAGS_REG) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
(define_insn "*setcc_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(match_operator:QI 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)]))]
+ [(reg FLAGS_REG) (const_int 0)]))]
""
"set%C1\t%0"
[(set_attr "type" "setcc")
(set_attr "mode" "QI")])
-(define_insn "setcc_2"
+(define_insn "*setcc_2"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
(match_operator:QI 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)]))]
+ [(reg FLAGS_REG) (const_int 0)]))]
""
"set%C1\t%0"
[(set_attr "type" "setcc")
@@ -12882,7 +13286,7 @@
(define_split
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(ne:QI (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(const_int 0)))]
""
[(set (match_dup 0) (match_dup 1))]
@@ -12893,7 +13297,7 @@
(define_split
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
(ne:QI (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(const_int 0)))]
""
[(set (match_dup 0) (match_dup 1))]
@@ -12904,7 +13308,7 @@
(define_split
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(eq:QI (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(const_int 0)))]
""
[(set (match_dup 0) (match_dup 1))]
@@ -12912,8 +13316,8 @@
rtx new_op1 = copy_rtx (operands[1]);
operands[1] = new_op1;
PUT_MODE (new_op1, QImode);
- PUT_CODE (new_op1, REVERSE_CONDITION (GET_CODE (new_op1),
- GET_MODE (XEXP (new_op1, 0))));
+ PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
+ GET_MODE (XEXP (new_op1, 0))));
/* Make sure that (a) the CCmode we have for the flags is strong
enough for the reversed compare or (b) we have a valid FP compare. */
@@ -12924,7 +13328,7 @@
(define_split
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
(eq:QI (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(const_int 0)))]
""
[(set (match_dup 0) (match_dup 1))]
@@ -12932,8 +13336,8 @@
rtx new_op1 = copy_rtx (operands[1]);
operands[1] = new_op1;
PUT_MODE (new_op1, QImode);
- PUT_CODE (new_op1, REVERSE_CONDITION (GET_CODE (new_op1),
- GET_MODE (XEXP (new_op1, 0))));
+ PUT_CODE (new_op1, ix86_reverse_condition (GET_CODE (new_op1),
+ GET_MODE (XEXP (new_op1, 0))));
/* Make sure that (a) the CCmode we have for the flags is strong
enough for the reversed compare or (b) we have a valid FP compare. */
@@ -12944,17 +13348,14 @@
;; The SSE store flag instructions saves 0 or 0xffffffff to the result.
;; subsequent logical operations are used to imitate conditional moves.
;; 0xffffffff is NaN, but not in normalized form, so we can't represent
-;; it directly. Further holding this value in pseudo register might bring
-;; problem in implicit normalization in spill code.
-;; So we don't define FLOAT_STORE_FLAG_VALUE and create these
-;; instructions after reload by splitting the conditional move patterns.
+;; it directly.
(define_insn "*sse_setccsf"
[(set (match_operand:SF 0 "register_operand" "=x")
(match_operator:SF 1 "sse_comparison_operator"
[(match_operand:SF 2 "register_operand" "0")
(match_operand:SF 3 "nonimmediate_operand" "xm")]))]
- "TARGET_SSE && reload_completed"
+ "TARGET_SSE"
"cmp%D1ss\t{%3, %0|%0, %3}"
[(set_attr "type" "ssecmp")
(set_attr "mode" "SF")])
@@ -12964,7 +13365,7 @@
(match_operator:DF 1 "sse_comparison_operator"
[(match_operand:DF 2 "register_operand" "0")
(match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
- "TARGET_SSE2 && reload_completed"
+ "TARGET_SSE2"
"cmp%D1sd\t{%3, %0|%0, %3}"
[(set_attr "type" "ssecmp")
(set_attr "mode" "DF")])
@@ -12973,7 +13374,7 @@
;; We ignore the overflow flag for signed branch instructions.
;; For all bCOND expanders, also expand the compare or test insn that
-;; generates reg 17. Generate an equality comparison if `beq' or `bne'.
+;; generates reg FLAGS_REG. Generate an equality comparison if `beq' or `bne'.
(define_expand "beq"
[(set (pc)
@@ -13060,7 +13461,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNORDERED, operands[0]); DONE;")
(define_expand "bordered"
@@ -13068,7 +13469,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (ORDERED, operands[0]); DONE;")
(define_expand "buneq"
@@ -13076,7 +13477,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNEQ, operands[0]); DONE;")
(define_expand "bunge"
@@ -13084,7 +13485,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNGE, operands[0]); DONE;")
(define_expand "bungt"
@@ -13092,7 +13493,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNGT, operands[0]); DONE;")
(define_expand "bunle"
@@ -13100,7 +13501,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNLE, operands[0]); DONE;")
(define_expand "bunlt"
@@ -13108,7 +13509,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNLT, operands[0]); DONE;")
(define_expand "bltgt"
@@ -13116,13 +13517,13 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (LTGT, operands[0]); DONE;")
(define_insn "*jcc_1"
[(set (pc)
(if_then_else (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
""
@@ -13140,7 +13541,7 @@
(define_insn "*jcc_2"
[(set (pc)
(if_then_else (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
""
@@ -13166,7 +13567,7 @@
(define_split
[(set (pc)
(if_then_else (ne (match_operator 0 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -13182,7 +13583,7 @@
(define_split
[(set (pc)
(if_then_else (eq (match_operator 0 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -13195,8 +13596,8 @@
rtx new_op0 = copy_rtx (operands[0]);
operands[0] = new_op0;
PUT_MODE (new_op0, VOIDmode);
- PUT_CODE (new_op0, REVERSE_CONDITION (GET_CODE (new_op0),
- GET_MODE (XEXP (new_op0, 0))));
+ PUT_CODE (new_op0, ix86_reverse_condition (GET_CODE (new_op0),
+ GET_MODE (XEXP (new_op0, 0))));
/* Make sure that (a) the CCmode we have for the flags is strong
enough for the reversed compare or (b) we have a valid FP compare. */
@@ -13208,18 +13609,17 @@
;; during early optimization. Splitting the operation apart early makes
;; for bad code when we want to reverse the operation.
-(define_insn "*fp_jcc_1"
+(define_insn "*fp_jcc_1_mixed"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "f")
- (match_operand 2 "register_operand" "f")])
+ [(match_operand 1 "register_operand" "f,x")
+ (match_operand 2 "nonimmediate_operand" "f,xm")])
(label_ref (match_operand 3 "" ""))
(pc)))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))]
- "TARGET_CMOVE && TARGET_80387
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))]
+ "TARGET_MIX_SSE_I387
+ && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
@@ -13227,44 +13627,44 @@
(define_insn "*fp_jcc_1_sse"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "f#x,x#f")
- (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
+ [(match_operand 1 "register_operand" "x")
+ (match_operand 2 "nonimmediate_operand" "xm")])
(label_ref (match_operand 3 "" ""))
(pc)))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))]
- "TARGET_80387
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))]
+ "TARGET_SSE_MATH
&& SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_1_sse_only"
+(define_insn "*fp_jcc_1_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "x")
- (match_operand 2 "nonimmediate_operand" "xm")])
+ [(match_operand 1 "register_operand" "f")
+ (match_operand 2 "register_operand" "f")])
(label_ref (match_operand 3 "" ""))
(pc)))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))]
- "SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))]
+ "TARGET_CMOVE && TARGET_80387
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_2"
+(define_insn "*fp_jcc_2_mixed"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "f")
- (match_operand 2 "register_operand" "f")])
+ [(match_operand 1 "register_operand" "f,x")
+ (match_operand 2 "nonimmediate_operand" "f,xm")])
(pc)
(label_ref (match_operand 3 "" ""))))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))]
- "TARGET_CMOVE && TARGET_80387
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))]
+ "TARGET_MIX_SSE_I387
+ && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
@@ -13272,41 +13672,42 @@
(define_insn "*fp_jcc_2_sse"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "f#x,x#f")
- (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
+ [(match_operand 1 "register_operand" "x")
+ (match_operand 2 "nonimmediate_operand" "xm")])
(pc)
(label_ref (match_operand 3 "" ""))))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))]
- "TARGET_80387
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))]
+ "TARGET_SSE_MATH
&& SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_2_sse_only"
+(define_insn "*fp_jcc_2_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "x")
- (match_operand 2 "nonimmediate_operand" "xm")])
+ [(match_operand 1 "register_operand" "f")
+ (match_operand 2 "register_operand" "f")])
(pc)
(label_ref (match_operand 3 "" ""))))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))]
- "SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))]
+ "TARGET_CMOVE && TARGET_80387
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_3"
+(define_insn "*fp_jcc_3_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "fm")])
(label_ref (match_operand 3 "" ""))
(pc)))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
(clobber (match_scratch:HI 4 "=a"))]
"TARGET_80387
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
@@ -13317,15 +13718,15 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_4"
+(define_insn "*fp_jcc_4_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "fm")])
(pc)
(label_ref (match_operand 3 "" ""))))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
(clobber (match_scratch:HI 4 "=a"))]
"TARGET_80387
&& (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
@@ -13336,15 +13737,15 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_5"
+(define_insn "*fp_jcc_5_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")])
(label_ref (match_operand 3 "" ""))
(pc)))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
(clobber (match_scratch:HI 4 "=a"))]
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
@@ -13352,22 +13753,65 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_6"
+(define_insn "*fp_jcc_6_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")])
(pc)
(label_ref (match_operand 3 "" ""))))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
+ (clobber (match_scratch:HI 4 "=a"))]
+ "TARGET_80387
+ && FLOAT_MODE_P (GET_MODE (operands[1]))
+ && GET_MODE (operands[1]) == GET_MODE (operands[2])
+ && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
+ "#")
+
+(define_insn "*fp_jcc_7_387"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand 1 "register_operand" "f")
+ (match_operand 2 "const0_operand" "X")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
(clobber (match_scratch:HI 4 "=a"))]
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
+ && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
+ && SELECT_CC_MODE (GET_CODE (operands[0]),
+ operands[1], operands[2]) == CCFPmode
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
+;; The order of operands in *fp_jcc_8_387 is forced by combine in
+;; simplify_comparison () function. Float operator is treated as RTX_OBJ
+;; with a precedence over other operators and is always put in the first
+;; place. Swap condition and operands to match ficom instruction.
+
+(define_insn "*fp_jcc_8<mode>_387"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operator 1 "float_operator"
+ [(match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r")])
+ (match_operand 3 "register_operand" "f,f")])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
+ (clobber (match_scratch:HI 5 "=a,a"))]
+ "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
+ && FLOAT_MODE_P (GET_MODE (operands[3]))
+ && GET_MODE (operands[1]) == GET_MODE (operands[3])
+ && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0])))
+ && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
+ && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))"
+ "#")
+
(define_split
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
@@ -13375,13 +13819,13 @@
(match_operand 2 "nonimmediate_operand" "")])
(match_operand 3 "" "")
(match_operand 4 "" "")))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))]
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))]
"reload_completed"
[(const_int 0)]
{
ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
- operands[3], operands[4], NULL_RTX);
+ operands[3], operands[4], NULL_RTX, NULL_RTX);
DONE;
})
@@ -13389,20 +13833,61 @@
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "")
- (match_operand 2 "nonimmediate_operand" "")])
+ (match_operand 2 "general_operand" "")])
(match_operand 3 "" "")
(match_operand 4 "" "")))
- (clobber (reg:CCFP 18))
- (clobber (reg:CCFP 17))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
(clobber (match_scratch:HI 5 "=a"))]
"reload_completed"
- [(set (pc)
- (if_then_else (match_dup 6)
- (match_dup 3)
- (match_dup 4)))]
+ [(const_int 0)]
{
ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
- operands[3], operands[4], operands[5]);
+ operands[3], operands[4], operands[5], NULL_RTX);
+ DONE;
+})
+
+(define_split
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operator 1 "float_operator"
+ [(match_operand:X87MODEI12 2 "memory_operand" "")])
+ (match_operand 3 "register_operand" "")])
+ (match_operand 4 "" "")
+ (match_operand 5 "" "")))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
+ (clobber (match_scratch:HI 6 "=a"))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]);
+ ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
+ operands[3], operands[7],
+ operands[4], operands[5], operands[6], NULL_RTX);
+ DONE;
+})
+
+;; %%% Kill this when reload knows how to do it.
+(define_split
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operator 1 "float_operator"
+ [(match_operand:X87MODEI12 2 "register_operand" "")])
+ (match_operand 3 "register_operand" "")])
+ (match_operand 4 "" "")
+ (match_operand 5 "" "")))
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:CCFP FLAGS_REG))
+ (clobber (match_scratch:HI 6 "=a"))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
+ operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]);
+ ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
+ operands[3], operands[7],
+ operands[4], operands[5], operands[6], operands[2]);
DONE;
})
@@ -13494,119 +13979,13 @@
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
-;; Loop instruction
-;;
-;; This is all complicated by the fact that since this is a jump insn
-;; we must handle our own reloads.
-
-(define_expand "doloop_end"
- [(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
- "!TARGET_64BIT && TARGET_USE_LOOP"
- "
-{
- /* Only use cloop on innermost loops. */
- if (INTVAL (operands[3]) > 1)
- FAIL;
- if (GET_MODE (operands[0]) != SImode)
- FAIL;
- emit_jump_insn (gen_doloop_end_internal (operands[4], operands[0],
- operands[0]));
- DONE;
-}")
-
-(define_insn "doloop_end_internal"
- [(set (pc)
- (if_then_else (ne (match_operand:SI 1 "register_operand" "c,?*r,?*r")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:SI 2 "register_operand" "=1,1,*m*r")
- (plus:SI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:SI 3 "=X,X,r"))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_USE_LOOP"
-{
- if (which_alternative != 0)
- return "#";
- if (get_attr_length (insn) == 2)
- return "%+loop\t%l0";
- else
- return "dec{l}\t%1\;%+jne\t%l0";
-}
- [(set_attr "ppro_uops" "many")
- (set (attr "length")
- (if_then_else (and (eq_attr "alternative" "0")
- (and (ge (minus (match_dup 0) (pc))
- (const_int -126))
- (lt (minus (match_dup 0) (pc))
- (const_int 128))))
- (const_int 2)
- (const_int 16)))
- ;; We don't know the type before shorten branches. Optimistically expect
- ;; the loop instruction to match.
- (set (attr "type") (const_string "ibr"))])
-
-(define_split
- [(set (pc)
- (if_then_else (ne (match_operand:SI 1 "register_operand" "")
- (const_int 1))
- (match_operand 0 "" "")
- (pc)))
- (set (match_dup 1)
- (plus:SI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:SI 2 ""))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_USE_LOOP
- && reload_completed
- && REGNO (operands[1]) != 2"
- [(parallel [(set (reg:CCZ 17)
- (compare:CCZ (plus:SI (match_dup 1) (const_int -1))
- (const_int 0)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int -1)))])
- (set (pc) (if_then_else (ne (reg:CCZ 17) (const_int 0))
- (match_dup 0)
- (pc)))]
- "")
-
-(define_split
- [(set (pc)
- (if_then_else (ne (match_operand:SI 1 "register_operand" "")
- (const_int 1))
- (match_operand 0 "" "")
- (pc)))
- (set (match_operand:SI 2 "nonimmediate_operand" "")
- (plus:SI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:SI 3 ""))
- (clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_USE_LOOP
- && reload_completed
- && (! REG_P (operands[2])
- || ! rtx_equal_p (operands[1], operands[2]))"
- [(set (match_dup 3) (match_dup 1))
- (parallel [(set (reg:CCZ 17)
- (compare:CCZ (plus:SI (match_dup 3) (const_int -1))
- (const_int 0)))
- (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
- (set (match_dup 2) (match_dup 3))
- (set (pc) (if_then_else (ne (reg:CCZ 17) (const_int 0))
- (match_dup 0)
- (pc)))]
- "")
-
;; Convert setcc + movzbl to xor + setcc if operands don't overlap.
(define_peephole2
- [(set (reg 17) (match_operand 0 "" ""))
+ [(set (reg FLAGS_REG) (match_operand 0 "" ""))
(set (match_operand:QI 1 "register_operand" "")
(match_operator:QI 2 "ix86_comparison_operator"
- [(reg 17) (const_int 0)]))
+ [(reg FLAGS_REG) (const_int 0)]))
(set (match_operand 3 "q_regs_operand" "")
(zero_extend (match_dup 1)))]
"(peep2_reg_dead_p (3, operands[1])
@@ -13616,7 +13995,7 @@
(set (strict_low_part (match_dup 5))
(match_dup 2))]
{
- operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17);
+ operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
operands[5] = gen_lowpart (QImode, operands[3]);
ix86_expand_clear (operands[3]);
})
@@ -13624,13 +14003,13 @@
;; Similar, but match zero_extendhisi2_and, which adds a clobber.
(define_peephole2
- [(set (reg 17) (match_operand 0 "" ""))
+ [(set (reg FLAGS_REG) (match_operand 0 "" ""))
(set (match_operand:QI 1 "register_operand" "")
(match_operator:QI 2 "ix86_comparison_operator"
- [(reg 17) (const_int 0)]))
+ [(reg FLAGS_REG) (const_int 0)]))
(parallel [(set (match_operand 3 "q_regs_operand" "")
(zero_extend (match_dup 1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"(peep2_reg_dead_p (3, operands[1])
|| operands_match_p (operands[1], operands[3]))
&& ! reg_overlap_mentioned_p (operands[3], operands[0])"
@@ -13638,7 +14017,7 @@
(set (strict_low_part (match_dup 5))
(match_dup 2))]
{
- operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17);
+ operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG);
operands[5] = gen_lowpart (QImode, operands[3]);
ix86_expand_clear (operands[3]);
})
@@ -13654,8 +14033,8 @@
(define_expand "call_pop"
[(parallel [(call (match_operand:QI 0 "" "")
(match_operand:SI 1 "" ""))
- (set (reg:SI 7)
- (plus:SI (reg:SI 7)
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
(match_operand:SI 3 "" "")))])]
"!TARGET_64BIT"
{
@@ -13666,7 +14045,7 @@
(define_insn "*call_pop_0"
[(call (mem:QI (match_operand:SI 0 "constant_call_address_operand" ""))
(match_operand:SI 1 "" ""))
- (set (reg:SI 7) (plus:SI (reg:SI 7)
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
(match_operand:SI 2 "immediate_operand" "")))]
"!TARGET_64BIT"
{
@@ -13680,7 +14059,7 @@
(define_insn "*call_pop_1"
[(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
(match_operand:SI 1 "" ""))
- (set (reg:SI 7) (plus:SI (reg:SI 7)
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
(match_operand:SI 2 "immediate_operand" "i")))]
"!TARGET_64BIT"
{
@@ -13735,7 +14114,7 @@
(match_operand 1 "" ""))]
"!SIBLING_CALL_P (insn) && !TARGET_64BIT"
{
- if (constant_call_address_operand (operands[0], QImode))
+ if (constant_call_address_operand (operands[0], Pmode))
return "call\t%P0";
return "call\t%A0";
}
@@ -13746,7 +14125,7 @@
(match_operand 1 "" ""))]
"SIBLING_CALL_P (insn) && !TARGET_64BIT"
{
- if (constant_call_address_operand (operands[0], QImode))
+ if (constant_call_address_operand (operands[0], Pmode))
return "jmp\t%P0";
return "jmp\t%A0";
}
@@ -13757,7 +14136,7 @@
(match_operand 1 "" ""))]
"!SIBLING_CALL_P (insn) && TARGET_64BIT"
{
- if (constant_call_address_operand (operands[0], QImode))
+ if (constant_call_address_operand (operands[0], Pmode))
return "call\t%P0";
return "call\t%A0";
}
@@ -13784,8 +14163,8 @@
[(parallel [(set (match_operand 0 "" "")
(call (match_operand:QI 1 "" "")
(match_operand:SI 2 "" "")))
- (set (reg:SI 7)
- (plus:SI (reg:SI 7)
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
(match_operand:SI 4 "" "")))])]
"!TARGET_64BIT"
{
@@ -13925,8 +14304,7 @@
"nop"
[(set_attr "length" "1")
(set_attr "length_immediate" "0")
- (set_attr "modrm" "0")
- (set_attr "ppro_uops" "one")])
+ (set_attr "modrm" "0")])
;; Align to 16-byte boundary, max skip in op0. Used to avoid
;; branch prediction penalty for the third jump in a 16-byte
@@ -13941,7 +14319,7 @@
#else
/* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that.
The align insn is used to avoid 3 jump instructions in the row to improve
- branch prediction and the benefits hardly outweight the cost of extra 8
+ branch prediction and the benefits hardly outweigh the cost of extra 8
nops on the average inserted by full alignment pseudo operation. */
#endif
return "";
@@ -13956,12 +14334,30 @@
(define_insn "set_got"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT"
+ { return output_set_got (operands[0], NULL_RTX); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
+
+(define_insn "set_got_labelled"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(label_ref (match_operand 1 "" ""))]
+ UNSPEC_SET_GOT))
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
- { return output_set_got (operands[0]); }
+ { return output_set_got (operands[0], operands[1]); }
[(set_attr "type" "multi")
(set_attr "length" "12")])
+(define_insn "set_got_rex64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(const_int 0)] UNSPEC_SET_GOT))]
+ "TARGET_64BIT"
+ "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
+ [(set_attr "type" "lea")
+ (set_attr "length" "6")])
+
(define_expand "epilogue"
[(const_int 1)]
""
@@ -13987,16 +14383,17 @@
emit_move_insn (tmp, ra);
if (Pmode == SImode)
- emit_insn (gen_eh_return_si (sa));
+ emit_jump_insn (gen_eh_return_si (sa));
else
- emit_insn (gen_eh_return_di (sa));
+ emit_jump_insn (gen_eh_return_di (sa));
emit_barrier ();
DONE;
})
(define_insn_and_split "eh_return_si"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "c")]
- UNSPECV_EH_RETURN)]
+ [(set (pc)
+ (unspec [(match_operand:SI 0 "register_operand" "c")]
+ UNSPEC_EH_RETURN))]
"!TARGET_64BIT"
"#"
"reload_completed"
@@ -14004,8 +14401,9 @@
"ix86_expand_epilogue (2); DONE;")
(define_insn_and_split "eh_return_di"
- [(unspec_volatile [(match_operand:DI 0 "register_operand" "c")]
- UNSPECV_EH_RETURN)]
+ [(set (pc)
+ (unspec [(match_operand:DI 0 "register_operand" "c")]
+ UNSPEC_EH_RETURN))]
"TARGET_64BIT"
"#"
"reload_completed"
@@ -14013,16 +14411,16 @@
"ix86_expand_epilogue (2); DONE;")
(define_insn "leave"
- [(set (reg:SI 7) (plus:SI (reg:SI 6) (const_int 4)))
- (set (reg:SI 6) (mem:SI (reg:SI 6)))
+ [(set (reg:SI SP_REG) (plus:SI (reg:SI BP_REG) (const_int 4)))
+ (set (reg:SI BP_REG) (mem:SI (reg:SI BP_REG)))
(clobber (mem:BLK (scratch)))]
"!TARGET_64BIT"
"leave"
[(set_attr "type" "leave")])
(define_insn "leave_rex64"
- [(set (reg:DI 7) (plus:DI (reg:DI 6) (const_int 8)))
- (set (reg:DI 6) (mem:DI (reg:DI 6)))
+ [(set (reg:DI SP_REG) (plus:DI (reg:DI BP_REG) (const_int 8)))
+ (set (reg:DI BP_REG) (mem:DI (reg:DI BP_REG)))
(clobber (mem:BLK (scratch)))]
"TARGET_64BIT"
"leave"
@@ -14033,7 +14431,7 @@
[(set (match_operand:SI 0 "register_operand" "")
(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "")))
(clobber (match_scratch:SI 2 ""))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
@@ -14041,73 +14439,118 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
(clobber (match_scratch:SI 2 "=&r"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_CMOVE"
"#"
"&& reload_completed"
[(set (match_dup 2) (const_int -1))
- (parallel [(set (reg:CCZ 17) (compare:CCZ (match_dup 1) (const_int 0)))
+ (parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
(set (match_dup 0) (ctz:SI (match_dup 1)))])
(set (match_dup 0) (if_then_else:SI
- (eq (reg:CCZ 17) (const_int 0))
+ (eq (reg:CCZ FLAGS_REG) (const_int 0))
(match_dup 2)
(match_dup 0)))
(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_insn_and_split "*ffs_no_cmove"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r")
(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
(clobber (match_scratch:SI 2 "=&q"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"#"
"reload_completed"
- [(parallel [(set (reg:CCZ 17) (compare:CCZ (match_dup 1) (const_int 0)))
+ [(parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
(set (match_dup 0) (ctz:SI (match_dup 1)))])
(set (strict_low_part (match_dup 3))
- (eq:QI (reg:CCZ 17) (const_int 0)))
+ (eq:QI (reg:CCZ FLAGS_REG) (const_int 0)))
(parallel [(set (match_dup 2) (neg:SI (match_dup 2)))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(parallel [(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
{
operands[3] = gen_lowpart (QImode, operands[2]);
ix86_expand_clear (operands[2]);
})
(define_insn "*ffssi_1"
- [(set (reg:CCZ 17)
+ [(set (reg:CCZ FLAGS_REG)
(compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm")
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(ctz:SI (match_dup 1)))]
""
"bsf{l}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")
- (set_attr "ppro_uops" "few")])
+ [(set_attr "prefix_0f" "1")])
+
+(define_expand "ffsdi2"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ffs:DI (match_operand:DI 1 "nonimmediate_operand" "")))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT && TARGET_CMOVE"
+ "")
+
+(define_insn_and_split "*ffs_rex64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ffs:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
+ (clobber (match_scratch:DI 2 "=&r"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && TARGET_CMOVE"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2) (const_int -1))
+ (parallel [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (match_dup 1) (const_int 0)))
+ (set (match_dup 0) (ctz:DI (match_dup 1)))])
+ (set (match_dup 0) (if_then_else:DI
+ (eq (reg:CCZ FLAGS_REG) (const_int 0))
+ (match_dup 2)
+ (match_dup 0)))
+ (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "")
+
+(define_insn "*ffsdi_1"
+ [(set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (match_operand:DI 1 "nonimmediate_operand" "rm")
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=r")
+ (ctz:DI (match_dup 1)))]
+ "TARGET_64BIT"
+ "bsf{q}\t{%1, %0|%0, %1}"
+ [(set_attr "prefix_0f" "1")])
(define_insn "ctzsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(ctz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"bsf{l}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")
- (set_attr "ppro_uops" "few")])
+ [(set_attr "prefix_0f" "1")])
+
+(define_insn "ctzdi2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ctz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "bsf{q}\t{%1, %0|%0, %1}"
+ [(set_attr "prefix_0f" "1")])
(define_expand "clzsi2"
[(parallel
[(set (match_operand:SI 0 "register_operand" "")
(minus:SI (const_int 31)
(clz:SI (match_operand:SI 1 "nonimmediate_operand" ""))))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(parallel
[(set (match_dup 0) (xor:SI (match_dup 0) (const_int 31)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
@@ -14115,11 +14558,31 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (const_int 31)
(clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"bsr{l}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")
- (set_attr "ppro_uops" "few")])
+ [(set_attr "prefix_0f" "1")])
+
+(define_expand "clzdi2"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (const_int 63)
+ (clz:DI (match_operand:DI 1 "nonimmediate_operand" ""))))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel
+ [(set (match_dup 0) (xor:DI (match_dup 0) (const_int 63)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT"
+ "")
+
+(define_insn "*bsr_rex64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (minus:DI (const_int 63)
+ (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm"))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "bsr{q}\t{%1, %0|%0, %1}"
+ [(set_attr "prefix_0f" "1")])
;; Thread-local storage patterns for ELF.
;;
@@ -14134,7 +14597,7 @@
UNSPEC_TLS_GD))
(clobber (match_scratch:SI 4 "=d"))
(clobber (match_scratch:SI 5 "=c"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_GNU_TLS"
"lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
[(set_attr "type" "multi")
@@ -14148,7 +14611,7 @@
UNSPEC_TLS_GD))
(clobber (match_scratch:SI 4 "=d"))
(clobber (match_scratch:SI 5 "=c"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_SUN_TLS"
"lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
@@ -14164,7 +14627,7 @@
UNSPEC_TLS_GD))
(clobber (match_scratch:SI 4 ""))
(clobber (match_scratch:SI 5 ""))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
{
if (flag_pic)
@@ -14174,13 +14637,19 @@
operands[2] = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (operands[2]));
}
+ if (TARGET_GNU2_TLS)
+ {
+ emit_insn (gen_tls_dynamic_gnu2_32
+ (operands[0], operands[1], operands[2]));
+ DONE;
+ }
operands[3] = ix86_tls_get_addr ();
})
(define_insn "*tls_global_dynamic_64"
[(set (match_operand:DI 0 "register_operand" "=a")
- (call (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
- (match_operand:DI 3 "" "")))
+ (call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
+ (match_operand:DI 3 "" "")))
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
UNSPEC_TLS_GD)]
"TARGET_64BIT"
@@ -14190,11 +14659,17 @@
(define_expand "tls_global_dynamic_64"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
- (call (mem:QI (match_dup 2)) (const_int 0)))
+ (call:DI (mem:QI (match_dup 2)) (const_int 0)))
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
UNSPEC_TLS_GD)])]
""
{
+ if (TARGET_GNU2_TLS)
+ {
+ emit_insn (gen_tls_dynamic_gnu2_64
+ (operands[0], operands[1]));
+ DONE;
+ }
operands[2] = ix86_tls_get_addr ();
})
@@ -14205,7 +14680,7 @@
UNSPEC_TLS_LD_BASE))
(clobber (match_scratch:SI 3 "=d"))
(clobber (match_scratch:SI 4 "=c"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_GNU_TLS"
"lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
[(set_attr "type" "multi")
@@ -14218,7 +14693,7 @@
UNSPEC_TLS_LD_BASE))
(clobber (match_scratch:SI 3 "=d"))
(clobber (match_scratch:SI 4 "=c"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_SUN_TLS"
"lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
@@ -14231,7 +14706,7 @@
UNSPEC_TLS_LD_BASE))
(clobber (match_scratch:SI 3 ""))
(clobber (match_scratch:SI 4 ""))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
{
if (flag_pic)
@@ -14241,13 +14716,19 @@
operands[1] = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (operands[1]));
}
+ if (TARGET_GNU2_TLS)
+ {
+ emit_insn (gen_tls_dynamic_gnu2_32
+ (operands[0], ix86_tls_module_base (), operands[1]));
+ DONE;
+ }
operands[2] = ix86_tls_get_addr ();
})
(define_insn "*tls_local_dynamic_base_64"
[(set (match_operand:DI 0 "register_operand" "=a")
- (call (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
- (match_operand:DI 2 "" "")))
+ (call:DI (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
+ (match_operand:DI 2 "" "")))
(unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
"TARGET_64BIT"
"lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1"
@@ -14256,10 +14737,16 @@
(define_expand "tls_local_dynamic_base_64"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
- (call (mem:QI (match_dup 1)) (const_int 0)))
+ (call:DI (mem:QI (match_dup 1)) (const_int 0)))
(unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
""
{
+ if (TARGET_GNU2_TLS)
+ {
+ emit_insn (gen_tls_dynamic_gnu2_64
+ (operands[0], ix86_tls_module_base ()));
+ DONE;
+ }
operands[1] = ix86_tls_get_addr ();
})
@@ -14276,7 +14763,7 @@
UNSPEC_DTPOFF))))
(clobber (match_scratch:SI 4 "=d"))
(clobber (match_scratch:SI 5 "=c"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"#"
""
@@ -14285,7 +14772,7 @@
UNSPEC_TLS_GD))
(clobber (match_dup 4))
(clobber (match_dup 5))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
;; Load and add the thread base pointer from %gs:0.
@@ -14305,7 +14792,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
(match_operand:SI 1 "register_operand" "0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
"add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
[(set_attr "type" "alu")
@@ -14329,7 +14816,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP)
(match_operand:DI 1 "register_operand" "0")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
[(set_attr "type" "alu")
@@ -14337,6 +14824,136 @@
(set_attr "length" "7")
(set_attr "memory" "load")
(set_attr "imm_disp" "false")])
+
+;; GNU2 TLS patterns can be split.
+
+(define_expand "tls_dynamic_gnu2_32"
+ [(set (match_dup 3)
+ (plus:SI (match_operand:SI 2 "register_operand" "")
+ (const:SI
+ (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLSDESC))))
+ (parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(match_dup 1) (match_dup 3)
+ (match_dup 2) (reg:SI SP_REG)]
+ UNSPEC_TLSDESC))
+ (clobber (reg:CC FLAGS_REG))])]
+ "!TARGET_64BIT && TARGET_GNU2_TLS"
+{
+ operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+ ix86_tls_descriptor_calls_expanded_in_cfun = true;
+})
+
+(define_insn "*tls_dynamic_lea_32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "b")
+ (const:SI
+ (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
+ UNSPEC_TLSDESC))))]
+ "!TARGET_64BIT && TARGET_GNU2_TLS"
+ "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")
+ (set_attr "length" "6")
+ (set_attr "length_address" "4")])
+
+(define_insn "*tls_dynamic_call_32"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
+ (match_operand:SI 2 "register_operand" "0")
+ ;; we have to make sure %ebx still points to the GOT
+ (match_operand:SI 3 "register_operand" "b")
+ (reg:SI SP_REG)]
+ UNSPEC_TLSDESC))
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT && TARGET_GNU2_TLS"
+ "call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}"
+ [(set_attr "type" "call")
+ (set_attr "length" "2")
+ (set_attr "length_address" "0")])
+
+(define_insn_and_split "*tls_dynamic_gnu2_combine_32"
+ [(set (match_operand:SI 0 "register_operand" "=&a")
+ (plus:SI
+ (unspec:SI [(match_operand:SI 3 "tls_modbase_operand" "")
+ (match_operand:SI 4 "" "")
+ (match_operand:SI 2 "register_operand" "b")
+ (reg:SI SP_REG)]
+ UNSPEC_TLSDESC)
+ (const:SI (unspec:SI
+ [(match_operand:SI 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPOFF))))
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT && TARGET_GNU2_TLS"
+ "#"
+ ""
+ [(set (match_dup 0) (match_dup 5))]
+{
+ operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+ emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
+})
+
+(define_expand "tls_dynamic_gnu2_64"
+ [(set (match_dup 2)
+ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLSDESC))
+ (parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
+ UNSPEC_TLSDESC))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT && TARGET_GNU2_TLS"
+{
+ operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+ ix86_tls_descriptor_calls_expanded_in_cfun = true;
+})
+
+(define_insn "*tls_dynamic_lea_64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLSDESC))]
+ "TARGET_64BIT && TARGET_GNU2_TLS"
+ "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
+ [(set_attr "type" "lea")
+ (set_attr "mode" "DI")
+ (set_attr "length" "7")
+ (set_attr "length_address" "4")])
+
+(define_insn "*tls_dynamic_call_64"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
+ (match_operand:DI 2 "register_operand" "0")
+ (reg:DI SP_REG)]
+ UNSPEC_TLSDESC))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && TARGET_GNU2_TLS"
+ "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
+ [(set_attr "type" "call")
+ (set_attr "length" "2")
+ (set_attr "length_address" "0")])
+
+(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
+ [(set (match_operand:DI 0 "register_operand" "=&a")
+ (plus:DI
+ (unspec:DI [(match_operand:DI 2 "tls_modbase_operand" "")
+ (match_operand:DI 3 "" "")
+ (reg:DI SP_REG)]
+ UNSPEC_TLSDESC)
+ (const:DI (unspec:DI
+ [(match_operand:DI 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPOFF))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && TARGET_GNU2_TLS"
+ "#"
+ ""
+ [(set (match_dup 0) (match_dup 4))]
+{
+ operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+ emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
+})
+
+;;
;; These patterns match the binary 387 instructions for addM3, subM3,
;; mulM3 and divM3. There are three patterns for each of DFmode and
@@ -14348,28 +14965,14 @@
;; Gcc is slightly more smart about handling normal two address instructions
;; so use special patterns for add and mull.
-(define_insn "*fop_sf_comm_nosse"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (match_operator:SF 3 "binary_fp_operator"
- [(match_operand:SF 1 "nonimmediate_operand" "%0")
- (match_operand:SF 2 "nonimmediate_operand" "fm")]))]
- "TARGET_80387 && !TARGET_SSE_MATH
- && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (if_then_else (match_operand:SF 3 "mult_operator" "")
- (const_string "fmul")
- (const_string "fop")))
- (set_attr "mode" "SF")])
-(define_insn "*fop_sf_comm"
- [(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
+(define_insn "*fop_sf_comm_mixed"
+ [(set (match_operand:SF 0 "register_operand" "=f,x")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "fm#x,xm#f")]))]
- "TARGET_80387 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
- && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'
+ (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))]
+ "TARGET_MIX_SSE_I387
+ && COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
@@ -14387,7 +14990,8 @@
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "nonimmediate_operand" "%0")
(match_operand:SF 2 "nonimmediate_operand" "xm")]))]
- "TARGET_SSE_MATH && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'
+ "TARGET_SSE_MATH
+ && COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
@@ -14396,94 +15000,28 @@
(const_string "sseadd")))
(set_attr "mode" "SF")])
-(define_insn "*fop_df_comm_nosse"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (match_operator:DF 3 "binary_fp_operator"
- [(match_operand:DF 1 "nonimmediate_operand" "%0")
- (match_operand:DF 2 "nonimmediate_operand" "fm")]))]
- "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH)
- && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'
+(define_insn "*fop_sf_comm_i387"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (match_operator:SF 3 "binary_fp_operator"
+ [(match_operand:SF 1 "nonimmediate_operand" "%0")
+ (match_operand:SF 2 "nonimmediate_operand" "fm")]))]
+ "TARGET_80387
+ && COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(if_then_else (match_operand:SF 3 "mult_operator" "")
(const_string "fmul")
(const_string "fop")))
- (set_attr "mode" "DF")])
-
-(define_insn "*fop_df_comm"
- [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
- (match_operator:DF 3 "binary_fp_operator"
- [(match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "fm#Y,Ym#f")]))]
- "TARGET_80387 && TARGET_SSE_MATH && TARGET_SSE2 && TARGET_MIX_SSE_I387
- && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (if_then_else (eq_attr "alternative" "1")
- (if_then_else (match_operand:SF 3 "mult_operator" "")
- (const_string "ssemul")
- (const_string "sseadd"))
- (if_then_else (match_operand:SF 3 "mult_operator" "")
- (const_string "fmul")
- (const_string "fop"))))
- (set_attr "mode" "DF")])
-
-(define_insn "*fop_df_comm_sse"
- [(set (match_operand:DF 0 "register_operand" "=Y")
- (match_operator:DF 3 "binary_fp_operator"
- [(match_operand:DF 1 "nonimmediate_operand" "%0")
- (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
- "TARGET_SSE2 && TARGET_SSE_MATH
- && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (if_then_else (match_operand:SF 3 "mult_operator" "")
- (const_string "ssemul")
- (const_string "sseadd")))
- (set_attr "mode" "DF")])
-
-(define_insn "*fop_xf_comm"
- [(set (match_operand:XF 0 "register_operand" "=f")
- (match_operator:XF 3 "binary_fp_operator"
- [(match_operand:XF 1 "register_operand" "%0")
- (match_operand:XF 2 "register_operand" "f")]))]
- "TARGET_80387
- && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (if_then_else (match_operand:XF 3 "mult_operator" "")
- (const_string "fmul")
- (const_string "fop")))
- (set_attr "mode" "XF")])
-
-(define_insn "*fop_sf_1_nosse"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (match_operator:SF 3 "binary_fp_operator"
- [(match_operand:SF 1 "nonimmediate_operand" "0,fm")
- (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
- "TARGET_80387 && !TARGET_SSE_MATH
- && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (cond [(match_operand:SF 3 "mult_operator" "")
- (const_string "fmul")
- (match_operand:SF 3 "div_operator" "")
- (const_string "fdiv")
- ]
- (const_string "fop")))
(set_attr "mode" "SF")])
-(define_insn "*fop_sf_1"
+(define_insn "*fop_sf_1_mixed"
[(set (match_operand:SF 0 "register_operand" "=f,f,x")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "nonimmediate_operand" "0,fm,0")
- (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm#f")]))]
- "TARGET_80387 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
- && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'
+ (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))]
+ "TARGET_MIX_SSE_I387
+ && !COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
@@ -14509,7 +15047,7 @@
[(match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonimmediate_operand" "xm")]))]
"TARGET_SSE_MATH
- && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'"
+ && !COMMUTATIVE_ARITH_P (operands[3])"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:SF 3 "mult_operator" "")
@@ -14520,13 +15058,32 @@
(const_string "sseadd")))
(set_attr "mode" "SF")])
+;; This pattern is not fully shadowed by the pattern above.
+(define_insn "*fop_sf_1_i387"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (match_operator:SF 3 "binary_fp_operator"
+ [(match_operand:SF 1 "nonimmediate_operand" "0,fm")
+ (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
+ "TARGET_80387 && !TARGET_SSE_MATH
+ && !COMMUTATIVE_ARITH_P (operands[3])
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (cond [(match_operand:SF 3 "mult_operator" "")
+ (const_string "fmul")
+ (match_operand:SF 3 "div_operator" "")
+ (const_string "fdiv")
+ ]
+ (const_string "fop")))
+ (set_attr "mode" "SF")])
+
;; ??? Add SSE splitters for these!
-(define_insn "*fop_sf_2"
+(define_insn "*fop_sf_2<mode>_i387"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(match_operator:SF 3 "binary_fp_operator"
- [(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,?r"))
+ [(float:SF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
(match_operand:SF 2 "register_operand" "0,0")]))]
- "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE_MATH"
+ "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:SF 3 "mult_operator" "")
@@ -14536,15 +15093,14 @@
]
(const_string "fop")))
(set_attr "fp_int_src" "true")
- (set_attr "ppro_uops" "many")
- (set_attr "mode" "SI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*fop_sf_3"
+(define_insn "*fop_sf_3<mode>_i387"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(match_operator:SF 3 "binary_fp_operator"
[(match_operand:SF 1 "register_operand" "0,0")
- (float:SF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))]
- "TARGET_80387 && TARGET_USE_FIOP && !TARGET_SSE_MATH"
+ (float:SF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
+ "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP && !TARGET_SSE_MATH"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:SF 3 "mult_operator" "")
@@ -14554,43 +15110,72 @@
]
(const_string "fop")))
(set_attr "fp_int_src" "true")
- (set_attr "ppro_uops" "many")
- (set_attr "mode" "SI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*fop_df_1_nosse"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
+(define_insn "*fop_df_comm_mixed"
+ [(set (match_operand:DF 0 "register_operand" "=f,Y")
(match_operator:DF 3 "binary_fp_operator"
- [(match_operand:DF 1 "nonimmediate_operand" "0,fm")
- (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
- "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH)
- && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'
+ [(match_operand:DF 1 "nonimmediate_operand" "%0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))]
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387
+ && COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
- (cond [(match_operand:DF 3 "mult_operator" "")
- (const_string "fmul")
- (match_operand:DF 3 "div_operator" "")
- (const_string "fdiv")
- ]
- (const_string "fop")))
+ (if_then_else (eq_attr "alternative" "1")
+ (if_then_else (match_operand:DF 3 "mult_operator" "")
+ (const_string "ssemul")
+ (const_string "sseadd"))
+ (if_then_else (match_operand:DF 3 "mult_operator" "")
+ (const_string "fmul")
+ (const_string "fop"))))
+ (set_attr "mode" "DF")])
+
+(define_insn "*fop_df_comm_sse"
+ [(set (match_operand:DF 0 "register_operand" "=Y")
+ (match_operator:DF 3 "binary_fp_operator"
+ [(match_operand:DF 1 "nonimmediate_operand" "%0")
+ (match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && COMMUTATIVE_ARITH_P (operands[3])
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (if_then_else (match_operand:DF 3 "mult_operator" "")
+ (const_string "ssemul")
+ (const_string "sseadd")))
(set_attr "mode" "DF")])
+(define_insn "*fop_df_comm_i387"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (match_operator:DF 3 "binary_fp_operator"
+ [(match_operand:DF 1 "nonimmediate_operand" "%0")
+ (match_operand:DF 2 "nonimmediate_operand" "fm")]))]
+ "TARGET_80387
+ && COMMUTATIVE_ARITH_P (operands[3])
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (if_then_else (match_operand:DF 3 "mult_operator" "")
+ (const_string "fmul")
+ (const_string "fop")))
+ (set_attr "mode" "DF")])
-(define_insn "*fop_df_1"
- [(set (match_operand:DF 0 "register_operand" "=f#Y,f#Y,Y#f")
+(define_insn "*fop_df_1_mixed"
+ [(set (match_operand:DF 0 "register_operand" "=f,f,Y")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "nonimmediate_operand" "0,fm,0")
- (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym#f")]))]
- "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
- && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'
+ (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))]
+ "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387
+ && !COMMUTATIVE_ARITH_P (operands[3])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(and (eq_attr "alternative" "2")
- (match_operand:SF 3 "mult_operator" ""))
+ (match_operand:DF 3 "mult_operator" ""))
(const_string "ssemul")
(and (eq_attr "alternative" "2")
- (match_operand:SF 3 "div_operator" ""))
+ (match_operand:DF 3 "div_operator" ""))
(const_string "ssediv")
(eq_attr "alternative" "2")
(const_string "sseadd")
@@ -14608,24 +15193,44 @@
[(match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "nonimmediate_operand" "Ym")]))]
"TARGET_SSE2 && TARGET_SSE_MATH
- && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'"
+ && !COMMUTATIVE_ARITH_P (operands[3])"
"* return output_387_binary_op (insn, operands);"
[(set_attr "mode" "DF")
(set (attr "type")
- (cond [(match_operand:SF 3 "mult_operator" "")
+ (cond [(match_operand:DF 3 "mult_operator" "")
(const_string "ssemul")
- (match_operand:SF 3 "div_operator" "")
+ (match_operand:DF 3 "div_operator" "")
(const_string "ssediv")
]
(const_string "sseadd")))])
+;; This pattern is not fully shadowed by the pattern above.
+(define_insn "*fop_df_1_i387"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (match_operator:DF 3 "binary_fp_operator"
+ [(match_operand:DF 1 "nonimmediate_operand" "0,fm")
+ (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
+ "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
+ && !COMMUTATIVE_ARITH_P (operands[3])
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (cond [(match_operand:DF 3 "mult_operator" "")
+ (const_string "fmul")
+ (match_operand:DF 3 "div_operator" "")
+ (const_string "fdiv")
+ ]
+ (const_string "fop")))
+ (set_attr "mode" "DF")])
+
;; ??? Add SSE splitters for these!
-(define_insn "*fop_df_2"
+(define_insn "*fop_df_2<mode>_i387"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(match_operator:DF 3 "binary_fp_operator"
- [(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,?r"))
+ [(float:DF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
(match_operand:DF 2 "register_operand" "0,0")]))]
- "TARGET_80387 && TARGET_USE_FIOP && !(TARGET_SSE2 && TARGET_SSE_MATH)"
+ "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
+ && !(TARGET_SSE2 && TARGET_SSE_MATH)"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:DF 3 "mult_operator" "")
@@ -14635,15 +15240,15 @@
]
(const_string "fop")))
(set_attr "fp_int_src" "true")
- (set_attr "ppro_uops" "many")
- (set_attr "mode" "SI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*fop_df_3"
+(define_insn "*fop_df_3<mode>_i387"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "register_operand" "0,0")
- (float:DF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))]
- "TARGET_80387 && TARGET_USE_FIOP && !(TARGET_SSE2 && TARGET_SSE_MATH)"
+ (float:DF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
+ "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP
+ && !(TARGET_SSE2 && TARGET_SSE_MATH)"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:DF 3 "mult_operator" "")
@@ -14653,15 +15258,14 @@
]
(const_string "fop")))
(set_attr "fp_int_src" "true")
- (set_attr "ppro_uops" "many")
- (set_attr "mode" "SI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*fop_df_4"
+(define_insn "*fop_df_4_i387"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(match_operator:DF 3 "binary_fp_operator"
[(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
(match_operand:DF 2 "register_operand" "0,f")]))]
- "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH)
+ "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
@@ -14673,7 +15277,7 @@
(const_string "fop")))
(set_attr "mode" "SF")])
-(define_insn "*fop_df_5"
+(define_insn "*fop_df_5_i387"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(match_operator:DF 3 "binary_fp_operator"
[(match_operand:DF 1 "register_operand" "0,f")
@@ -14690,7 +15294,7 @@
(const_string "fop")))
(set_attr "mode" "SF")])
-(define_insn "*fop_df_6"
+(define_insn "*fop_df_6_i387"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(match_operator:DF 3 "binary_fp_operator"
[(float_extend:DF
@@ -14708,13 +15312,27 @@
(const_string "fop")))
(set_attr "mode" "SF")])
-(define_insn "*fop_xf_1"
+(define_insn "*fop_xf_comm_i387"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (match_operator:XF 3 "binary_fp_operator"
+ [(match_operand:XF 1 "register_operand" "%0")
+ (match_operand:XF 2 "register_operand" "f")]))]
+ "TARGET_80387
+ && COMMUTATIVE_ARITH_P (operands[3])"
+ "* return output_387_binary_op (insn, operands);"
+ [(set (attr "type")
+ (if_then_else (match_operand:XF 3 "mult_operator" "")
+ (const_string "fmul")
+ (const_string "fop")))
+ (set_attr "mode" "XF")])
+
+(define_insn "*fop_xf_1_i387"
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_fp_operator"
[(match_operand:XF 1 "register_operand" "0,f")
(match_operand:XF 2 "register_operand" "f,0")]))]
"TARGET_80387
- && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'"
+ && !COMMUTATIVE_ARITH_P (operands[3])"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:XF 3 "mult_operator" "")
@@ -14725,12 +15343,12 @@
(const_string "fop")))
(set_attr "mode" "XF")])
-(define_insn "*fop_xf_2"
+(define_insn "*fop_xf_2<mode>_i387"
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_fp_operator"
- [(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r"))
+ [(float:XF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r"))
(match_operand:XF 2 "register_operand" "0,0")]))]
- "TARGET_80387 && TARGET_USE_FIOP"
+ "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:XF 3 "mult_operator" "")
@@ -14740,15 +15358,14 @@
]
(const_string "fop")))
(set_attr "fp_int_src" "true")
- (set_attr "mode" "SI")
- (set_attr "ppro_uops" "many")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*fop_xf_3"
+(define_insn "*fop_xf_3<mode>_i387"
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_fp_operator"
[(match_operand:XF 1 "register_operand" "0,0")
- (float:XF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))]
- "TARGET_80387 && TARGET_USE_FIOP"
+ (float:XF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))]
+ "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP"
"* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
[(set (attr "type")
(cond [(match_operand:XF 3 "mult_operator" "")
@@ -14758,10 +15375,9 @@
]
(const_string "fop")))
(set_attr "fp_int_src" "true")
- (set_attr "mode" "SI")
- (set_attr "ppro_uops" "many")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*fop_xf_4"
+(define_insn "*fop_xf_4_i387"
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_fp_operator"
[(float_extend:XF (match_operand 1 "nonimmediate_operand" "fm,0"))
@@ -14777,7 +15393,7 @@
(const_string "fop")))
(set_attr "mode" "SF")])
-(define_insn "*fop_xf_5"
+(define_insn "*fop_xf_5_i387"
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_fp_operator"
[(match_operand:XF 1 "register_operand" "0,f")
@@ -14794,7 +15410,7 @@
(const_string "fop")))
(set_attr "mode" "SF")])
-(define_insn "*fop_xf_6"
+(define_insn "*fop_xf_6_i387"
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_fp_operator"
[(float_extend:XF
@@ -14815,7 +15431,7 @@
(define_split
[(set (match_operand 0 "register_operand" "")
(match_operator 3 "binary_fp_operator"
- [(float (match_operand:SI 1 "register_operand" ""))
+ [(float (match_operand:X87MODEI12 1 "register_operand" ""))
(match_operand 2 "register_operand" "")]))]
"TARGET_80387 && reload_completed
&& FLOAT_MODE_P (GET_MODE (operands[0]))"
@@ -14836,7 +15452,7 @@
[(set (match_operand 0 "register_operand" "")
(match_operator 3 "binary_fp_operator"
[(match_operand 1 "register_operand" "")
- (float (match_operand:SI 2 "register_operand" ""))]))]
+ (float (match_operand:X87MODEI12 2 "register_operand" ""))]))]
"TARGET_80387 && reload_completed
&& FLOAT_MODE_P (GET_MODE (operands[0]))"
[(const_int 0)]
@@ -14857,17 +15473,16 @@
(define_expand "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "")
(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "")))]
- "(! TARGET_NO_FANCY_MATH_387 && TARGET_80387) || TARGET_SSE_MATH"
+ "TARGET_USE_FANCY_MATH_387 || TARGET_SSE_MATH"
{
if (!TARGET_SSE_MATH)
operands[1] = force_reg (SFmode, operands[1]);
})
-(define_insn "sqrtsf2_1"
- [(set (match_operand:SF 0 "register_operand" "=f#x,x#f")
- (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0#x,xm#f")))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (TARGET_SSE_MATH && TARGET_MIX_SSE_I387)"
+(define_insn "*sqrtsf2_mixed"
+ [(set (match_operand:SF 0 "register_operand" "=f,x")
+ (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))]
+ "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387"
"@
fsqrt
sqrtss\t{%1, %0|%0, %1}"
@@ -14875,20 +15490,19 @@
(set_attr "mode" "SF,SF")
(set_attr "athlon_decode" "direct,*")])
-(define_insn "sqrtsf2_1_sse_only"
+(define_insn "*sqrtsf2_sse"
[(set (match_operand:SF 0 "register_operand" "=x")
(sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "xm")))]
- "TARGET_SSE_MATH && (!TARGET_80387 || !TARGET_MIX_SSE_I387)"
+ "TARGET_SSE_MATH"
"sqrtss\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
(set_attr "mode" "SF")
(set_attr "athlon_decode" "*")])
-(define_insn "sqrtsf2_i387"
+(define_insn "*sqrtsf2_i387"
[(set (match_operand:SF 0 "register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && !TARGET_SSE_MATH"
+ "TARGET_USE_FANCY_MATH_387"
"fsqrt"
[(set_attr "type" "fpspc")
(set_attr "mode" "SF")
@@ -14897,18 +15511,16 @@
(define_expand "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "")
(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "")))]
- "(! TARGET_NO_FANCY_MATH_387 && TARGET_80387)
- || (TARGET_SSE2 && TARGET_SSE_MATH)"
+ "TARGET_USE_FANCY_MATH_387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
{
- if (!TARGET_SSE2 || !TARGET_SSE_MATH)
+ if (!(TARGET_SSE2 && TARGET_SSE_MATH))
operands[1] = force_reg (DFmode, operands[1]);
})
-(define_insn "sqrtdf2_1"
- [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f")
- (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0#Y,Ym#f")))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387)"
+(define_insn "*sqrtdf2_mixed"
+ [(set (match_operand:DF 0 "register_operand" "=f,Y")
+ (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))]
+ "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387"
"@
fsqrt
sqrtsd\t{%1, %0|%0, %1}"
@@ -14916,31 +15528,30 @@
(set_attr "mode" "DF,DF")
(set_attr "athlon_decode" "direct,*")])
-(define_insn "sqrtdf2_1_sse_only"
+(define_insn "*sqrtdf2_sse"
[(set (match_operand:DF 0 "register_operand" "=Y")
(sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
- "TARGET_SSE2 && TARGET_SSE_MATH && (!TARGET_80387 || !TARGET_MIX_SSE_I387)"
+ "TARGET_SSE2 && TARGET_SSE_MATH"
"sqrtsd\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "*")])
-(define_insn "sqrtdf2_i387"
+(define_insn "*sqrtdf2_i387"
[(set (match_operand:DF 0 "register_operand" "=f")
(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (!TARGET_SSE2 || !TARGET_SSE_MATH)"
+ "TARGET_USE_FANCY_MATH_387"
"fsqrt"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "direct")])
-(define_insn "*sqrtextendsfdf2"
+(define_insn "*sqrtextendsfdf2_i387"
[(set (match_operand:DF 0 "register_operand" "=f")
(sqrt:DF (float_extend:DF
(match_operand:SF 1 "register_operand" "0"))))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && !(TARGET_SSE2 && TARGET_SSE_MATH)"
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)"
"fsqrt"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")
@@ -14949,46 +15560,217 @@
(define_insn "sqrtxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
- "TARGET_80387 && !TARGET_NO_FANCY_MATH_387
- && (TARGET_IEEE_FP || flag_unsafe_math_optimizations) "
+ "TARGET_USE_FANCY_MATH_387"
"fsqrt"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")
(set_attr "athlon_decode" "direct")])
-(define_insn "*sqrtextenddfxf2"
+(define_insn "*sqrtextendsfxf2_i387"
[(set (match_operand:XF 0 "register_operand" "=f")
(sqrt:XF (float_extend:XF
- (match_operand:DF 1 "register_operand" "0"))))]
- "TARGET_80387 && !TARGET_NO_FANCY_MATH_387"
+ (match_operand:SF 1 "register_operand" "0"))))]
+ "TARGET_USE_FANCY_MATH_387"
"fsqrt"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")
(set_attr "athlon_decode" "direct")])
-(define_insn "*sqrtextendsfxf2"
+(define_insn "*sqrtextenddfxf2_i387"
[(set (match_operand:XF 0 "register_operand" "=f")
(sqrt:XF (float_extend:XF
- (match_operand:SF 1 "register_operand" "0"))))]
- "TARGET_80387 && !TARGET_NO_FANCY_MATH_387"
+ (match_operand:DF 1 "register_operand" "0"))))]
+ "TARGET_USE_FANCY_MATH_387"
"fsqrt"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")
(set_attr "athlon_decode" "direct")])
-(define_insn "sindf2"
+(define_insn "fpremxf4"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "0")
+ (match_operand:XF 3 "register_operand" "1")]
+ UNSPEC_FPREM_F))
+ (set (match_operand:XF 1 "register_operand" "=u")
+ (unspec:XF [(match_dup 2) (match_dup 3)]
+ UNSPEC_FPREM_U))
+ (set (reg:CCFP FPSR_REG)
+ (unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fprem"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
+(define_expand "fmodsf3"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))
+ (use (match_operand:SF 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx label = gen_label_rtx ();
+
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
+
+ emit_insn(gen_extendsfxf2 (op1, operands[1]));
+ emit_insn(gen_extendsfxf2 (op2, operands[2]));
+
+ emit_label (label);
+
+ emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
+ ix86_emit_fp_unordered_jump (label);
+
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
+ DONE;
+})
+
+(define_expand "fmoddf3"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))
+ (use (match_operand:DF 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx label = gen_label_rtx ();
+
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_extenddfxf2 (op2, operands[2]));
+
+ emit_label (label);
+
+ emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
+ ix86_emit_fp_unordered_jump (label);
+
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
+ DONE;
+})
+
+(define_expand "fmodxf3"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))
+ (use (match_operand:XF 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ rtx label = gen_label_rtx ();
+
+ emit_label (label);
+
+ emit_insn (gen_fpremxf4 (operands[1], operands[2],
+ operands[1], operands[2]));
+ ix86_emit_fp_unordered_jump (label);
+
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
+
+(define_insn "fprem1xf4"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "0")
+ (match_operand:XF 3 "register_operand" "1")]
+ UNSPEC_FPREM1_F))
+ (set (match_operand:XF 1 "register_operand" "=u")
+ (unspec:XF [(match_dup 2) (match_dup 3)]
+ UNSPEC_FPREM1_U))
+ (set (reg:CCFP FPSR_REG)
+ (unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fprem1"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
+(define_expand "dremsf3"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))
+ (use (match_operand:SF 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx label = gen_label_rtx ();
+
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
+
+ emit_insn(gen_extendsfxf2 (op1, operands[1]));
+ emit_insn(gen_extendsfxf2 (op2, operands[2]));
+
+ emit_label (label);
+
+ emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
+ ix86_emit_fp_unordered_jump (label);
+
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
+ DONE;
+})
+
+(define_expand "dremdf3"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))
+ (use (match_operand:DF 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx label = gen_label_rtx ();
+
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx op2 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_extenddfxf2 (op2, operands[2]));
+
+ emit_label (label);
+
+ emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
+ ix86_emit_fp_unordered_jump (label);
+
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
+ DONE;
+})
+
+(define_expand "dremxf3"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))
+ (use (match_operand:XF 2 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ rtx label = gen_label_rtx ();
+
+ emit_label (label);
+
+ emit_insn (gen_fprem1xf4 (operands[1], operands[2],
+ operands[1], operands[2]));
+ ix86_emit_fp_unordered_jump (label);
+
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
+
+(define_insn "*sindf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
"fsin"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")])
-(define_insn "sinsf2"
+(define_insn "*sinsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_SIN))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
"fsin"
[(set_attr "type" "fpspc")
@@ -14999,34 +15781,37 @@
(unspec:DF [(float_extend:DF
(match_operand:SF 1 "register_operand" "0"))]
UNSPEC_SIN))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
"fsin"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")])
-(define_insn "sinxf2"
+(define_insn "*sinxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))]
- "TARGET_80387 && !TARGET_NO_FANCY_MATH_387
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
"fsin"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")])
-(define_insn "cosdf2"
+(define_insn "*cosdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_COS))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
"fcos"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")])
-(define_insn "cossf2"
+(define_insn "*cossf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_COS))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
"fcos"
[(set_attr "type" "fpspc")
@@ -15037,38 +15822,324 @@
(unspec:DF [(float_extend:DF
(match_operand:SF 1 "register_operand" "0"))]
UNSPEC_COS))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
"fcos"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")])
-(define_insn "cosxf2"
+(define_insn "*cosxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
"fcos"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")])
+;; With sincos pattern defined, sin and cos builtin function will be
+;; expanded to sincos pattern with one of its outputs left unused.
+;; Cse pass will detected, if two sincos patterns can be combined,
+;; otherwise sincos pattern will be split back to sin or cos pattern,
+;; depending on the unused output.
+
+(define_insn "sincosdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 2 "register_operand" "0")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:DF 1 "register_operand" "=u")
+ (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+ "fsincos"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DF")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (unspec:DF [(match_operand:DF 2 "register_operand" "")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:DF 1 "register_operand" "")
+ (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
+ && !reload_completed && !reload_in_progress"
+ [(set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_SIN))]
+ "")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (unspec:DF [(match_operand:DF 2 "register_operand" "")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:DF 1 "register_operand" "")
+ (unspec:DF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
+ && !reload_completed && !reload_in_progress"
+ [(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_COS))]
+ "")
+
+(define_insn "sincossf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 2 "register_operand" "0")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:SF 1 "register_operand" "=u")
+ (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+ "fsincos"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "SF")])
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (unspec:SF [(match_operand:SF 2 "register_operand" "")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:SF 1 "register_operand" "")
+ (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
+ && !reload_completed && !reload_in_progress"
+ [(set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_SIN))]
+ "")
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (unspec:SF [(match_operand:SF 2 "register_operand" "")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:SF 1 "register_operand" "")
+ (unspec:SF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
+ && !reload_completed && !reload_in_progress"
+ [(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_COS))]
+ "")
+
+(define_insn "*sincosextendsfdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(float_extend:DF
+ (match_operand:SF 2 "register_operand" "0"))]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:DF 1 "register_operand" "=u")
+ (unspec:DF [(float_extend:DF
+ (match_dup 2))] UNSPEC_SINCOS_SIN))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+ "fsincos"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DF")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (unspec:DF [(float_extend:DF
+ (match_operand:SF 2 "register_operand" ""))]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:DF 1 "register_operand" "")
+ (unspec:DF [(float_extend:DF
+ (match_dup 2))] UNSPEC_SINCOS_SIN))]
+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
+ && !reload_completed && !reload_in_progress"
+ [(set (match_dup 1) (unspec:DF [(float_extend:DF
+ (match_dup 2))] UNSPEC_SIN))]
+ "")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (unspec:DF [(float_extend:DF
+ (match_operand:SF 2 "register_operand" ""))]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:DF 1 "register_operand" "")
+ (unspec:DF [(float_extend:DF
+ (match_dup 2))] UNSPEC_SINCOS_SIN))]
+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
+ && !reload_completed && !reload_in_progress"
+ [(set (match_dup 0) (unspec:DF [(float_extend:DF
+ (match_dup 2))] UNSPEC_COS))]
+ "")
+
+(define_insn "sincosxf3"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "0")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:XF 1 "register_operand" "=u")
+ (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fsincos"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:XF 1 "register_operand" "")
+ (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[0]))
+ && !reload_completed && !reload_in_progress"
+ [(set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_SIN))]
+ "")
+
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "")]
+ UNSPEC_SINCOS_COS))
+ (set (match_operand:XF 1 "register_operand" "")
+ (unspec:XF [(match_dup 2)] UNSPEC_SINCOS_SIN))]
+ "find_regno_note (insn, REG_UNUSED, REGNO (operands[1]))
+ && !reload_completed && !reload_in_progress"
+ [(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_COS))]
+ "")
+
+(define_insn "*tandf3_1"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 2 "register_operand" "0")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:DF 1 "register_operand" "=u")
+ (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+ "fptan"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DF")])
+
+;; optimize sequence: fptan
+;; fstp %st(0)
+;; fld1
+;; into fptan insn.
+
+(define_peephole2
+ [(parallel[(set (match_operand:DF 0 "register_operand" "")
+ (unspec:DF [(match_operand:DF 2 "register_operand" "")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:DF 1 "register_operand" "")
+ (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])
+ (set (match_dup 0)
+ (match_operand:DF 3 "immediate_operand" ""))]
+ "standard_80387_constant_p (operands[3]) == 2"
+ [(parallel[(set (match_dup 0) (unspec:DF [(match_dup 2)] UNSPEC_TAN_ONE))
+ (set (match_dup 1) (unspec:DF [(match_dup 2)] UNSPEC_TAN_TAN))])]
+ "")
+
+(define_expand "tandf2"
+ [(parallel [(set (match_dup 2)
+ (unspec:DF [(match_operand:DF 1 "register_operand" "")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:DF 0 "register_operand" "")
+ (unspec:DF [(match_dup 1)] UNSPEC_TAN_TAN))])]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (DFmode);
+})
+
+(define_insn "*tansf3_1"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 2 "register_operand" "0")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:SF 1 "register_operand" "=u")
+ (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+ "fptan"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "SF")])
+
+;; optimize sequence: fptan
+;; fstp %st(0)
+;; fld1
+;; into fptan insn.
+
+(define_peephole2
+ [(parallel[(set (match_operand:SF 0 "register_operand" "")
+ (unspec:SF [(match_operand:SF 2 "register_operand" "")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:SF 1 "register_operand" "")
+ (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])
+ (set (match_dup 0)
+ (match_operand:SF 3 "immediate_operand" ""))]
+ "standard_80387_constant_p (operands[3]) == 2"
+ [(parallel[(set (match_dup 0) (unspec:SF [(match_dup 2)] UNSPEC_TAN_ONE))
+ (set (match_dup 1) (unspec:SF [(match_dup 2)] UNSPEC_TAN_TAN))])]
+ "")
+
+(define_expand "tansf2"
+ [(parallel [(set (match_dup 2)
+ (unspec:SF [(match_operand:SF 1 "register_operand" "")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:SF 0 "register_operand" "")
+ (unspec:SF [(match_dup 1)] UNSPEC_TAN_TAN))])]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (SFmode);
+})
+
+(define_insn "*tanxf3_1"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "0")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:XF 1 "register_operand" "=u")
+ (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fptan"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
+;; optimize sequence: fptan
+;; fstp %st(0)
+;; fld1
+;; into fptan insn.
+
+(define_peephole2
+ [(parallel[(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:XF 1 "register_operand" "")
+ (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])
+ (set (match_dup 0)
+ (match_operand:XF 3 "immediate_operand" ""))]
+ "standard_80387_constant_p (operands[3]) == 2"
+ [(parallel[(set (match_dup 0) (unspec:XF [(match_dup 2)] UNSPEC_TAN_ONE))
+ (set (match_dup 1) (unspec:XF [(match_dup 2)] UNSPEC_TAN_TAN))])]
+ "")
+
+(define_expand "tanxf2"
+ [(parallel [(set (match_dup 2)
+ (unspec:XF [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_TAN_ONE))
+ (set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_dup 1)] UNSPEC_TAN_TAN))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (XFmode);
+})
+
(define_insn "atan2df3_1"
[(set (match_operand:DF 0 "register_operand" "=f")
(unspec:DF [(match_operand:DF 2 "register_operand" "0")
(match_operand:DF 1 "register_operand" "u")]
UNSPEC_FPATAN))
(clobber (match_scratch:DF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
"fpatan"
[(set_attr "type" "fpspc")
(set_attr "mode" "DF")])
(define_expand "atan2df3"
- [(use (match_operand:DF 0 "register_operand" "=f"))
- (use (match_operand:DF 2 "register_operand" "0"))
- (use (match_operand:DF 1 "register_operand" "u"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 2 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx copy = gen_reg_rtx (DFmode);
@@ -15077,23 +16148,39 @@
DONE;
})
+(define_expand "atandf2"
+ [(parallel [(set (match_operand:DF 0 "register_operand" "")
+ (unspec:DF [(match_dup 2)
+ (match_operand:DF 1 "register_operand" "")]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:DF 3 ""))])]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (DFmode);
+ emit_move_insn (operands[2], CONST1_RTX (DFmode)); /* fld1 */
+})
+
(define_insn "atan2sf3_1"
[(set (match_operand:SF 0 "register_operand" "=f")
(unspec:SF [(match_operand:SF 2 "register_operand" "0")
(match_operand:SF 1 "register_operand" "u")]
UNSPEC_FPATAN))
(clobber (match_scratch:SF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
"fpatan"
[(set_attr "type" "fpspc")
(set_attr "mode" "SF")])
(define_expand "atan2sf3"
- [(use (match_operand:SF 0 "register_operand" "=f"))
- (use (match_operand:SF 2 "register_operand" "0"))
- (use (match_operand:SF 1 "register_operand" "u"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 2 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx copy = gen_reg_rtx (SFmode);
@@ -15102,23 +16189,37 @@
DONE;
})
+(define_expand "atansf2"
+ [(parallel [(set (match_operand:SF 0 "register_operand" "")
+ (unspec:SF [(match_dup 2)
+ (match_operand:SF 1 "register_operand" "")]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:SF 3 ""))])]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (SFmode);
+ emit_move_insn (operands[2], CONST1_RTX (SFmode)); /* fld1 */
+})
+
(define_insn "atan2xf3_1"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 2 "register_operand" "0")
(match_operand:XF 1 "register_operand" "u")]
UNSPEC_FPATAN))
(clobber (match_scratch:XF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
"fpatan"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")])
(define_expand "atan2xf3"
- [(use (match_operand:XF 0 "register_operand" "=f"))
- (use (match_operand:XF 2 "register_operand" "0"))
- (use (match_operand:XF 1 "register_operand" "u"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 2 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
rtx copy = gen_reg_rtx (XFmode);
@@ -15127,70 +16228,213 @@
DONE;
})
-(define_insn "*fyl2x_sfxf3"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (unspec:SF [(match_operand:SF 2 "register_operand" "0")
- (match_operand:XF 1 "register_operand" "u")]
- UNSPEC_FYL2X))
- (clobber (match_scratch:SF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_expand "atanxf2"
+ [(parallel [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_dup 2)
+ (match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:XF 3 ""))])]
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
- "fyl2x"
- [(set_attr "type" "fpspc")
- (set_attr "mode" "SF")])
+{
+ operands[2] = gen_reg_rtx (XFmode);
+ emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */
+})
-(define_insn "*fyl2x_dfxf3"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(match_operand:DF 2 "register_operand" "0")
- (match_operand:XF 1 "register_operand" "u")]
- UNSPEC_FYL2X))
- (clobber (match_scratch:DF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_expand "asindf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
+ (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
+ (set (match_dup 6) (sqrt:XF (match_dup 5)))
+ (parallel [(set (match_dup 7)
+ (unspec:XF [(match_dup 6) (match_dup 2)]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:XF 8 ""))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 7)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
- "fyl2x"
- [(set_attr "type" "fpspc")
- (set_attr "mode" "DF")])
+{
+ int i;
+
+ for (i=2; i<8; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+
+ emit_move_insn (operands[4], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "asinsf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
+ (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
+ (set (match_dup 6) (sqrt:XF (match_dup 5)))
+ (parallel [(set (match_dup 7)
+ (unspec:XF [(match_dup 6) (match_dup 2)]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:XF 8 ""))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 7)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=2; i<8; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+
+ emit_move_insn (operands[4], CONST1_RTX (XFmode)); /* fld1 */
+})
-(define_insn "*fyl2x_xf3"
+(define_expand "asinxf2"
+ [(set (match_dup 2)
+ (mult:XF (match_operand:XF 1 "register_operand" "")
+ (match_dup 1)))
+ (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
+ (set (match_dup 5) (sqrt:XF (match_dup 4)))
+ (parallel [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_dup 5) (match_dup 1)]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:XF 6 ""))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=2; i<6; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+
+ emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "acosdf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
+ (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
+ (set (match_dup 6) (sqrt:XF (match_dup 5)))
+ (parallel [(set (match_dup 7)
+ (unspec:XF [(match_dup 2) (match_dup 6)]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:XF 8 ""))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 7)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=2; i<8; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+
+ emit_move_insn (operands[4], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "acossf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (set (match_dup 3) (mult:XF (match_dup 2) (match_dup 2)))
+ (set (match_dup 5) (minus:XF (match_dup 4) (match_dup 3)))
+ (set (match_dup 6) (sqrt:XF (match_dup 5)))
+ (parallel [(set (match_dup 7)
+ (unspec:XF [(match_dup 2) (match_dup 6)]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:XF 8 ""))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 7)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=2; i<8; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+
+ emit_move_insn (operands[4], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "acosxf2"
+ [(set (match_dup 2)
+ (mult:XF (match_operand:XF 1 "register_operand" "")
+ (match_dup 1)))
+ (set (match_dup 4) (minus:XF (match_dup 3) (match_dup 2)))
+ (set (match_dup 5) (sqrt:XF (match_dup 4)))
+ (parallel [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_dup 1) (match_dup 5)]
+ UNSPEC_FPATAN))
+ (clobber (match_scratch:XF 6 ""))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=2; i<6; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+
+ emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_insn "fyl2x_xf3"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 2 "register_operand" "0")
(match_operand:XF 1 "register_operand" "u")]
UNSPEC_FYL2X))
(clobber (match_scratch:XF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
"fyl2x"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")])
(define_expand "logsf2"
- [(parallel [(set (match_operand:SF 0 "register_operand" "")
- (unspec:SF [(match_operand:SF 1 "register_operand" "")
- (match_dup 2)] UNSPEC_FYL2X))
- (clobber (match_scratch:SF 3 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (parallel [(set (match_dup 4)
+ (unspec:XF [(match_dup 2)
+ (match_dup 3)] UNSPEC_FYL2X))
+ (clobber (match_scratch:XF 5 ""))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 4)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx temp;
operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+ operands[4] = gen_reg_rtx (XFmode);
+
temp = standard_80387_constant_rtx (4); /* fldln2 */
- emit_move_insn (operands[2], temp);
+ emit_move_insn (operands[3], temp);
})
(define_expand "logdf2"
- [(parallel [(set (match_operand:DF 0 "register_operand" "")
- (unspec:DF [(match_operand:DF 1 "register_operand" "")
- (match_dup 2)] UNSPEC_FYL2X))
- (clobber (match_scratch:DF 3 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (parallel [(set (match_dup 4)
+ (unspec:XF [(match_dup 2)
+ (match_dup 3)] UNSPEC_FYL2X))
+ (clobber (match_scratch:XF 5 ""))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 4)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx temp;
operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+ operands[4] = gen_reg_rtx (XFmode);
+
temp = standard_80387_constant_rtx (4); /* fldln2 */
- emit_move_insn (operands[2], temp);
+ emit_move_insn (operands[3], temp);
})
(define_expand "logxf2"
@@ -15198,7 +16442,7 @@
(unspec:XF [(match_operand:XF 1 "register_operand" "")
(match_dup 2)] UNSPEC_FYL2X))
(clobber (match_scratch:XF 3 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
rtx temp;
@@ -15208,62 +16452,274 @@
emit_move_insn (operands[2], temp);
})
-(define_insn "*fscale_sfxf3"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (unspec:SF [(match_operand:XF 2 "register_operand" "0")
- (match_operand:XF 1 "register_operand" "u")]
- UNSPEC_FSCALE))
- (clobber (match_scratch:SF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_expand "log10sf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (parallel [(set (match_dup 4)
+ (unspec:XF [(match_dup 2)
+ (match_dup 3)] UNSPEC_FYL2X))
+ (clobber (match_scratch:XF 5 ""))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 4)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
- "fscale\;fstp\t%y1"
- [(set_attr "type" "fpspc")
- (set_attr "mode" "SF")])
+{
+ rtx temp;
-(define_insn "*fscale_dfxf3"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(match_operand:XF 2 "register_operand" "0")
- (match_operand:XF 1 "register_operand" "u")]
- UNSPEC_FSCALE))
- (clobber (match_scratch:DF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+ operands[4] = gen_reg_rtx (XFmode);
+
+ temp = standard_80387_constant_rtx (3); /* fldlg2 */
+ emit_move_insn (operands[3], temp);
+})
+
+(define_expand "log10df2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (parallel [(set (match_dup 4)
+ (unspec:XF [(match_dup 2)
+ (match_dup 3)] UNSPEC_FYL2X))
+ (clobber (match_scratch:XF 5 ""))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 4)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
- "fscale\;fstp\t%y1"
- [(set_attr "type" "fpspc")
- (set_attr "mode" "DF")])
+{
+ rtx temp;
-(define_insn "*fscale_xf3"
+ operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+ operands[4] = gen_reg_rtx (XFmode);
+
+ temp = standard_80387_constant_rtx (3); /* fldlg2 */
+ emit_move_insn (operands[3], temp);
+})
+
+(define_expand "log10xf2"
+ [(parallel [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "")
+ (match_dup 2)] UNSPEC_FYL2X))
+ (clobber (match_scratch:XF 3 ""))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ rtx temp;
+
+ operands[2] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (3); /* fldlg2 */
+ emit_move_insn (operands[2], temp);
+})
+
+(define_expand "log2sf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (parallel [(set (match_dup 4)
+ (unspec:XF [(match_dup 2)
+ (match_dup 3)] UNSPEC_FYL2X))
+ (clobber (match_scratch:XF 5 ""))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 4)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+ operands[4] = gen_reg_rtx (XFmode);
+
+ emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "log2df2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (parallel [(set (match_dup 4)
+ (unspec:XF [(match_dup 2)
+ (match_dup 3)] UNSPEC_FYL2X))
+ (clobber (match_scratch:XF 5 ""))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 4)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+ operands[4] = gen_reg_rtx (XFmode);
+
+ emit_move_insn (operands[3], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "log2xf2"
+ [(parallel [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "")
+ (match_dup 2)] UNSPEC_FYL2X))
+ (clobber (match_scratch:XF 3 ""))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (XFmode);
+ emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_insn "fyl2xp1_xf3"
[(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(match_operand:XF 2 "register_operand" "0")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "0")
(match_operand:XF 1 "register_operand" "u")]
- UNSPEC_FSCALE))
+ UNSPEC_FYL2XP1))
(clobber (match_scratch:XF 3 "=1"))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
- "fscale\;fstp\t%y1"
+ "fyl2xp1"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")])
-(define_insn "*frndintxf2"
+(define_expand "log1psf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ ix86_emit_i387_log1p (op0, op1);
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "log1pdf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ ix86_emit_i387_log1p (op0, op1);
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "log1pxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ ix86_emit_i387_log1p (operands[0], operands[1]);
+ DONE;
+})
+
+(define_insn "*fxtractxf3"
[(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
- UNSPEC_FRNDINT))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ (unspec:XF [(match_operand:XF 2 "register_operand" "0")]
+ UNSPEC_XTRACT_FRACT))
+ (set (match_operand:XF 1 "register_operand" "=u")
+ (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))]
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
- "frndint"
+ "fxtract"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")])
+(define_expand "logbsf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (parallel [(set (match_dup 3)
+ (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
+ (set (match_dup 4)
+ (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 4)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+ operands[4] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "logbdf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (parallel [(set (match_dup 3)
+ (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_FRACT))
+ (set (match_dup 4)
+ (unspec:XF [(match_dup 2)] UNSPEC_XTRACT_EXP))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 4)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+ operands[4] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "logbxf2"
+ [(parallel [(set (match_dup 2)
+ (unspec:XF [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_XTRACT_FRACT))
+ (set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "ilogbsi2"
+ [(parallel [(set (match_dup 2)
+ (unspec:XF [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_XTRACT_FRACT))
+ (set (match_operand:XF 3 "register_operand" "")
+ (unspec:XF [(match_dup 1)] UNSPEC_XTRACT_EXP))])
+ (parallel [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (match_dup 3)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (XFmode);
+})
+
(define_insn "*f2xm1xf2"
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "register_operand" "0")]
UNSPEC_F2XM1))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
"f2xm1"
[(set_attr "type" "fpspc")
(set_attr "mode" "XF")])
+(define_insn "*fscalexf4"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 2 "register_operand" "0")
+ (match_operand:XF 3 "register_operand" "1")]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_operand:XF 1 "register_operand" "=u")
+ (unspec:XF [(match_dup 2) (match_dup 3)]
+ UNSPEC_FSCALE_EXP))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fscale"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
(define_expand "expsf2"
[(set (match_dup 2)
(float_extend:XF (match_operand:SF 1 "register_operand" "")))
@@ -15272,16 +16728,22 @@
(set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
(set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
(set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
- (parallel [(set (match_operand:SF 0 "register_operand" "")
- (unspec:SF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE))
- (clobber (match_scratch:SF 5 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ (parallel [(set (match_dup 10)
+ (unspec:XF [(match_dup 9) (match_dup 5)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 11)
+ (unspec:XF [(match_dup 9) (match_dup 5)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 10)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx temp;
int i;
- for (i=2; i<10; i++)
+ for (i=2; i<12; i++)
operands[i] = gen_reg_rtx (XFmode);
temp = standard_80387_constant_rtx (5); /* fldl2e */
emit_move_insn (operands[3], temp);
@@ -15296,16 +16758,22 @@
(set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
(set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
(set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
- (parallel [(set (match_operand:DF 0 "register_operand" "")
- (unspec:DF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE))
- (clobber (match_scratch:DF 5 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ (parallel [(set (match_dup 10)
+ (unspec:XF [(match_dup 9) (match_dup 5)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 11)
+ (unspec:XF [(match_dup 9) (match_dup 5)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 10)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
rtx temp;
int i;
- for (i=2; i<10; i++)
+ for (i=2; i<12; i++)
operands[i] = gen_reg_rtx (XFmode);
temp = standard_80387_constant_rtx (5); /* fldl2e */
emit_move_insn (operands[3], temp);
@@ -15320,89 +16788,1231 @@
(set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
(set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
(parallel [(set (match_operand:XF 0 "register_operand" "")
- (unspec:XF [(match_dup 8) (match_dup 4)] UNSPEC_FSCALE))
- (clobber (match_scratch:XF 5 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+ (unspec:XF [(match_dup 8) (match_dup 4)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 9)
+ (unspec:XF [(match_dup 8) (match_dup 4)]
+ UNSPEC_FSCALE_EXP))])]
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
rtx temp;
int i;
- for (i=2; i<9; i++)
+ for (i=2; i<10; i++)
operands[i] = gen_reg_rtx (XFmode);
temp = standard_80387_constant_rtx (5); /* fldl2e */
emit_move_insn (operands[2], temp);
emit_move_insn (operands[7], CONST1_RTX (XFmode)); /* fld1 */
})
-(define_expand "atansf2"
- [(parallel [(set (match_operand:SF 0 "register_operand" "")
- (unspec:SF [(match_dup 2)
- (match_operand:SF 1 "register_operand" "")]
- UNSPEC_FPATAN))
- (clobber (match_scratch:SF 3 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_expand "exp10sf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
+ (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
+ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
+ (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
+ (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
+ (parallel [(set (match_dup 10)
+ (unspec:XF [(match_dup 9) (match_dup 5)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 11)
+ (unspec:XF [(match_dup 9) (match_dup 5)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 10)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- operands[2] = gen_reg_rtx (SFmode);
- emit_move_insn (operands[2], CONST1_RTX (SFmode)); /* fld1 */
+ rtx temp;
+ int i;
+
+ for (i=2; i<12; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (6); /* fldl2t */
+ emit_move_insn (operands[3], temp);
+ emit_move_insn (operands[8], CONST1_RTX (XFmode)); /* fld1 */
})
-(define_expand "atandf2"
- [(parallel [(set (match_operand:DF 0 "register_operand" "")
- (unspec:DF [(match_dup 2)
- (match_operand:DF 1 "register_operand" "")]
- UNSPEC_FPATAN))
- (clobber (match_scratch:DF 3 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_expand "exp10df2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
+ (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
+ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
+ (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
+ (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8)))
+ (parallel [(set (match_dup 10)
+ (unspec:XF [(match_dup 9) (match_dup 5)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 11)
+ (unspec:XF [(match_dup 9) (match_dup 5)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 10)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
&& flag_unsafe_math_optimizations"
{
- operands[2] = gen_reg_rtx (DFmode);
- emit_move_insn (operands[2], CONST1_RTX (DFmode)); /* fld1 */
+ rtx temp;
+ int i;
+
+ for (i=2; i<12; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (6); /* fldl2t */
+ emit_move_insn (operands[3], temp);
+ emit_move_insn (operands[8], CONST1_RTX (XFmode)); /* fld1 */
})
-(define_expand "atanxf2"
- [(parallel [(set (match_operand:XF 0 "register_operand" "")
- (unspec:XF [(match_dup 2)
- (match_operand:XF 1 "register_operand" "")]
- UNSPEC_FPATAN))
- (clobber (match_scratch:XF 3 ""))])]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+(define_expand "exp10xf2"
+ [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
+ (match_dup 2)))
+ (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
+ (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
+ (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
+ (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7)))
+ (parallel [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_dup 8) (match_dup 4)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 9)
+ (unspec:XF [(match_dup 8) (match_dup 4)]
+ UNSPEC_FSCALE_EXP))])]
+ "TARGET_USE_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
{
- operands[2] = gen_reg_rtx (XFmode);
- emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */
+ rtx temp;
+ int i;
+
+ for (i=2; i<10; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (6); /* fldl2t */
+ emit_move_insn (operands[2], temp);
+ emit_move_insn (operands[7], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "exp2sf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
+ (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
+ (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
+ (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
+ (parallel [(set (match_dup 8)
+ (unspec:XF [(match_dup 7) (match_dup 3)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 9)
+ (unspec:XF [(match_dup 7) (match_dup 3)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 8)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=2; i<10; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "exp2df2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
+ (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
+ (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
+ (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
+ (parallel [(set (match_dup 8)
+ (unspec:XF [(match_dup 7) (match_dup 3)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 9)
+ (unspec:XF [(match_dup 7) (match_dup 3)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 8)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=2; i<10; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "exp2xf2"
+ [(set (match_dup 2) (match_operand:XF 1 "register_operand" ""))
+ (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_FRNDINT))
+ (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3)))
+ (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1))
+ (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6)))
+ (parallel [(set (match_operand:XF 0 "register_operand" "")
+ (unspec:XF [(match_dup 7) (match_dup 3)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 8)
+ (unspec:XF [(match_dup 7) (match_dup 3)]
+ UNSPEC_FSCALE_EXP))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=2; i<9; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "expm1df2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
+ (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
+ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
+ (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
+ (parallel [(set (match_dup 8)
+ (unspec:XF [(match_dup 7) (match_dup 5)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 9)
+ (unspec:XF [(match_dup 7) (match_dup 5)]
+ UNSPEC_FSCALE_EXP))])
+ (parallel [(set (match_dup 11)
+ (unspec:XF [(match_dup 10) (match_dup 9)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 12)
+ (unspec:XF [(match_dup 10) (match_dup 9)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
+ (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 14)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx temp;
+ int i;
+
+ for (i=2; i<15; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (5); /* fldl2e */
+ emit_move_insn (operands[3], temp);
+ emit_move_insn (operands[10], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "expm1sf2"
+ [(set (match_dup 2)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3)))
+ (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT))
+ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5)))
+ (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1))
+ (parallel [(set (match_dup 8)
+ (unspec:XF [(match_dup 7) (match_dup 5)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 9)
+ (unspec:XF [(match_dup 7) (match_dup 5)]
+ UNSPEC_FSCALE_EXP))])
+ (parallel [(set (match_dup 11)
+ (unspec:XF [(match_dup 10) (match_dup 9)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 12)
+ (unspec:XF [(match_dup 10) (match_dup 9)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_dup 13) (minus:XF (match_dup 11) (match_dup 10)))
+ (set (match_dup 14) (plus:XF (match_dup 13) (match_dup 8)))
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 14)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx temp;
+ int i;
+
+ for (i=2; i<15; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (5); /* fldl2e */
+ emit_move_insn (operands[3], temp);
+ emit_move_insn (operands[10], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "expm1xf2"
+ [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "")
+ (match_dup 2)))
+ (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT))
+ (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4)))
+ (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1))
+ (parallel [(set (match_dup 7)
+ (unspec:XF [(match_dup 6) (match_dup 4)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 8)
+ (unspec:XF [(match_dup 6) (match_dup 4)]
+ UNSPEC_FSCALE_EXP))])
+ (parallel [(set (match_dup 10)
+ (unspec:XF [(match_dup 9) (match_dup 8)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 11)
+ (unspec:XF [(match_dup 9) (match_dup 8)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_dup 12) (minus:XF (match_dup 10) (match_dup 9)))
+ (set (match_operand:XF 0 "register_operand" "")
+ (plus:XF (match_dup 12) (match_dup 7)))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ rtx temp;
+ int i;
+
+ for (i=2; i<13; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+ temp = standard_80387_constant_rtx (5); /* fldl2e */
+ emit_move_insn (operands[2], temp);
+ emit_move_insn (operands[9], CONST1_RTX (XFmode)); /* fld1 */
+})
+
+(define_expand "ldexpdf3"
+ [(set (match_dup 3)
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (set (match_dup 4)
+ (float:XF (match_operand:SI 2 "register_operand" "")))
+ (parallel [(set (match_dup 5)
+ (unspec:XF [(match_dup 3) (match_dup 4)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 6)
+ (unspec:XF [(match_dup 3) (match_dup 4)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_dup 5)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=3; i<7; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "ldexpsf3"
+ [(set (match_dup 3)
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (set (match_dup 4)
+ (float:XF (match_operand:SI 2 "register_operand" "")))
+ (parallel [(set (match_dup 5)
+ (unspec:XF [(match_dup 3) (match_dup 4)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 6)
+ (unspec:XF [(match_dup 3) (match_dup 4)]
+ UNSPEC_FSCALE_EXP))])
+ (set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_dup 5)))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=3; i<7; i++)
+ operands[i] = gen_reg_rtx (XFmode);
+})
+
+(define_expand "ldexpxf3"
+ [(set (match_dup 3)
+ (float:XF (match_operand:SI 2 "register_operand" "")))
+ (parallel [(set (match_operand:XF 0 " register_operand" "")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "")
+ (match_dup 3)]
+ UNSPEC_FSCALE_FRACT))
+ (set (match_dup 4)
+ (unspec:XF [(match_dup 1) (match_dup 3)]
+ UNSPEC_FSCALE_EXP))])]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ int i;
+
+ for (i=3; i<5; i++)
+ operands[i] = gen_reg_rtx (XFmode);
})
+
+(define_insn "frndintxf2"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "frndint"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "XF")])
+
+(define_expand "rintdf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2 (op0, op1));
+
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "rintsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2 (op0, op1));
+
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "rintxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ emit_insn (gen_frndintxf2 (operands[0], operands[1]));
+ DONE;
+})
+
+(define_insn_and_split "*fistdi2_1"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ if (memory_operand (operands[0], VOIDmode))
+ emit_insn (gen_fistdi2 (operands[0], operands[1]));
+ else
+ {
+ operands[2] = assign_386_stack_local (DImode, SLOT_TEMP);
+ emit_insn (gen_fistdi2_with_temp (operands[0], operands[1],
+ operands[2]));
+ }
+ DONE;
+}
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DI")])
+
+(define_insn "fistdi2"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FIST))
+ (clobber (match_scratch:XF 2 "=&1f"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DI")])
+
+(define_insn "fistdi2_with_temp"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST))
+ (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
+ (clobber (match_scratch:XF 3 "=&1f,&1f"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "#"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "DI")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))
+ (clobber (match_operand:DI 2 "memory_operand" ""))
+ (clobber (match_scratch 3 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 2) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
+ (clobber (match_dup 3))])
+ (set (match_dup 0) (match_dup 2))]
+ "")
+
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))
+ (clobber (match_operand:DI 2 "memory_operand" ""))
+ (clobber (match_scratch 3 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST))
+ (clobber (match_dup 3))])]
+ "")
+
+(define_insn_and_split "*fist<mode>2_1"
+ [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FIST))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ operands[2] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
+ emit_insn (gen_fist<mode>2_with_temp (operands[0], operands[1],
+ operands[2]));
+ DONE;
+}
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fist<mode>2"
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FIST))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fist<mode>2_with_temp"
+ [(set (match_operand:X87MODEI12 0 "register_operand" "=r")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FIST))
+ (clobber (match_operand:X87MODEI12 2 "memory_operand" "=m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "#"
+ [(set_attr "type" "fpspc")
+ (set_attr "mode" "<MODE>")])
+
+(define_split
+ [(set (match_operand:X87MODEI12 0 "register_operand" "")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))
+ (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 2) (unspec:X87MODEI12 [(match_dup 1)]
+ UNSPEC_FIST))
+ (set (match_dup 0) (match_dup 2))]
+ "")
+
+(define_split
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))
+ (clobber (match_operand:X87MODEI12 2 "memory_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
+ UNSPEC_FIST))]
+ "")
+
+(define_expand "lrint<mode>2"
+ [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
+ (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+ "")
+
+;; Rounding mode control word calculation could clobber FLAGS_REG.
+(define_insn_and_split "frndintxf2_floor"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_FLOOR))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ ix86_optimize_mode_switching[I387_FLOOR] = 1;
+
+ operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+ operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
+
+ emit_insn (gen_frndintxf2_floor_i387 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+}
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "XF")])
+
+(define_insn "frndintxf2_floor_i387"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "XF")])
+
+(define_expand "floorxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ emit_insn (gen_frndintxf2_floor (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "floordf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_floor (op0, op1));
+
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "floorsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_floor (op0, op1));
+
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_insn_and_split "*fist<mode>2_floor_1"
+ [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
+ (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST_FLOOR))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ ix86_optimize_mode_switching[I387_FLOOR] = 1;
+
+ operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+ operands[3] = assign_386_stack_local (HImode, SLOT_CW_FLOOR);
+ if (memory_operand (operands[0], VOIDmode))
+ emit_insn (gen_fist<mode>2_floor (operands[0], operands[1],
+ operands[2], operands[3]));
+ else
+ {
+ operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
+ emit_insn (gen_fist<mode>2_floor_with_temp (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4]));
+ }
+ DONE;
+}
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fistdi2_floor"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FIST_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))
+ (clobber (match_scratch:XF 4 "=&1f"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "DI")])
+
+(define_insn "fistdi2_floor_with_temp"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" "m,m"))
+ (use (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
+ (clobber (match_scratch:XF 5 "=&1f,&1f"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "#"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "DI")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:DI 4 "memory_operand" ""))
+ (clobber (match_scratch 5 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
+ (use (match_dup 2))
+ (use (match_dup 3))
+ (clobber (match_dup 5))])
+ (set (match_dup 0) (match_dup 4))]
+ "")
+
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:DI 4 "memory_operand" ""))
+ (clobber (match_scratch 5 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_FLOOR))
+ (use (match_dup 2))
+ (use (match_dup 3))
+ (clobber (match_dup 5))])]
+ "")
+
+(define_insn "fist<mode>2_floor"
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FIST_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fist<mode>2_floor_with_temp"
+ [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" "m,m"))
+ (use (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "#"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "floor")
+ (set_attr "mode" "<MODE>")])
+
+(define_split
+ [(set (match_operand:X87MODEI12 0 "register_operand" "")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
+ UNSPEC_FIST_FLOOR))
+ (use (match_dup 2))
+ (use (match_dup 3))])
+ (set (match_dup 0) (match_dup 4))]
+ "")
+
+(define_split
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_FLOOR))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
+ UNSPEC_FIST_FLOOR))
+ (use (match_dup 2))
+ (use (match_dup 3))])]
+ "")
+
+(define_expand "lfloor<mode>2"
+ [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
+ (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_FLOOR))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+ "")
+
+;; Rounding mode control word calculation could clobber FLAGS_REG.
+(define_insn_and_split "frndintxf2_ceil"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_CEIL))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ ix86_optimize_mode_switching[I387_CEIL] = 1;
+
+ operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+ operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
+
+ emit_insn (gen_frndintxf2_ceil_i387 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+}
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "XF")])
+
+(define_insn "frndintxf2_ceil_i387"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_CEIL))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "XF")])
+
+(define_expand "ceilxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ emit_insn (gen_frndintxf2_ceil (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "ceildf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_ceil (op0, op1));
+
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "ceilsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_ceil (op0, op1));
+
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_insn_and_split "*fist<mode>2_ceil_1"
+ [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "=m,?r")
+ (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST_CEIL))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ ix86_optimize_mode_switching[I387_CEIL] = 1;
+
+ operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+ operands[3] = assign_386_stack_local (HImode, SLOT_CW_CEIL);
+ if (memory_operand (operands[0], VOIDmode))
+ emit_insn (gen_fist<mode>2_ceil (operands[0], operands[1],
+ operands[2], operands[3]));
+ else
+ {
+ operands[4] = assign_386_stack_local (<MODE>mode, SLOT_TEMP);
+ emit_insn (gen_fist<mode>2_ceil_with_temp (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4]));
+ }
+ DONE;
+}
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fistdi2_ceil"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FIST_CEIL))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))
+ (clobber (match_scratch:XF 4 "=&1f"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "DI")])
+
+(define_insn "fistdi2_ceil_with_temp"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST_CEIL))
+ (use (match_operand:HI 2 "memory_operand" "m,m"))
+ (use (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:DI 4 "memory_operand" "=m,m"))
+ (clobber (match_scratch:XF 5 "=&1f,&1f"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "#"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "DI")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_CEIL))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:DI 4 "memory_operand" ""))
+ (clobber (match_scratch 5 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 4) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
+ (use (match_dup 2))
+ (use (match_dup 3))
+ (clobber (match_dup 5))])
+ (set (match_dup 0) (match_dup 4))]
+ "")
+
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (unspec:DI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_CEIL))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:DI 4 "memory_operand" ""))
+ (clobber (match_scratch 5 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_FIST_CEIL))
+ (use (match_dup 2))
+ (use (match_dup 3))
+ (clobber (match_dup 5))])]
+ "")
+
+(define_insn "fist<mode>2_ceil"
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "=m")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FIST_CEIL))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "* return output_fix_trunc (insn, operands, 0);"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "fist<mode>2_ceil_with_temp"
+ [(set (match_operand:X87MODEI12 0 "nonimmediate_operand" "=m,?r")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "f,f")]
+ UNSPEC_FIST_CEIL))
+ (use (match_operand:HI 2 "memory_operand" "m,m"))
+ (use (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" "=m,m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "#"
+ [(set_attr "type" "fistp")
+ (set_attr "i387_cw" "ceil")
+ (set_attr "mode" "<MODE>")])
+
+(define_split
+ [(set (match_operand:X87MODEI12 0 "register_operand" "")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_CEIL))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 4) (unspec:X87MODEI12 [(match_dup 1)]
+ UNSPEC_FIST_CEIL))
+ (use (match_dup 2))
+ (use (match_dup 3))])
+ (set (match_dup 0) (match_dup 4))]
+ "")
+
+(define_split
+ [(set (match_operand:X87MODEI12 0 "memory_operand" "")
+ (unspec:X87MODEI12 [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_CEIL))
+ (use (match_operand:HI 2 "memory_operand" ""))
+ (use (match_operand:HI 3 "memory_operand" ""))
+ (clobber (match_operand:X87MODEI12 4 "memory_operand" ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (unspec:X87MODEI12 [(match_dup 1)]
+ UNSPEC_FIST_CEIL))
+ (use (match_dup 2))
+ (use (match_dup 3))])]
+ "")
+
+(define_expand "lceil<mode>2"
+ [(parallel [(set (match_operand:X87MODEI 0 "nonimmediate_operand" "")
+ (unspec:X87MODEI [(match_operand:XF 1 "register_operand" "")]
+ UNSPEC_FIST_CEIL))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+ "")
+
+;; Rounding mode control word calculation could clobber FLAGS_REG.
+(define_insn_and_split "frndintxf2_trunc"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_TRUNC))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ ix86_optimize_mode_switching[I387_TRUNC] = 1;
+
+ operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+ operands[3] = assign_386_stack_local (HImode, SLOT_CW_TRUNC);
+
+ emit_insn (gen_frndintxf2_trunc_i387 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+}
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "XF")])
+
+(define_insn "frndintxf2_trunc_i387"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_TRUNC))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fldcw\t%3\n\tfrndint\n\tfldcw\t%2"
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "trunc")
+ (set_attr "mode" "XF")])
+
+(define_expand "btruncxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ emit_insn (gen_frndintxf2_trunc (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "btruncdf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_trunc (op0, op1));
+
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "btruncsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_trunc (op0, op1));
+
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+;; Rounding mode control word calculation could clobber FLAGS_REG.
+(define_insn_and_split "frndintxf2_mask_pm"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_MASK_PM))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations
+ && !(reload_completed || reload_in_progress)"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ ix86_optimize_mode_switching[I387_MASK_PM] = 1;
+
+ operands[2] = assign_386_stack_local (HImode, SLOT_CW_STORED);
+ operands[3] = assign_386_stack_local (HImode, SLOT_CW_MASK_PM);
+
+ emit_insn (gen_frndintxf2_mask_pm_i387 (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+}
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "mask_pm")
+ (set_attr "mode" "XF")])
+
+(define_insn "frndintxf2_mask_pm_i387"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")]
+ UNSPEC_FRNDINT_MASK_PM))
+ (use (match_operand:HI 2 "memory_operand" "m"))
+ (use (match_operand:HI 3 "memory_operand" "m"))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+ "fldcw\t%3\n\tfrndint\n\tfclex\n\tfldcw\t%2"
+ [(set_attr "type" "frndint")
+ (set_attr "i387_cw" "mask_pm")
+ (set_attr "mode" "XF")])
+
+(define_expand "nearbyintxf2"
+ [(use (match_operand:XF 0 "register_operand" ""))
+ (use (match_operand:XF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && flag_unsafe_math_optimizations"
+{
+ emit_insn (gen_frndintxf2_mask_pm (operands[0], operands[1]));
+
+ DONE;
+})
+
+(define_expand "nearbyintdf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!(TARGET_SSE2 && TARGET_SSE_MATH) || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extenddfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_mask_pm (op0, op1));
+
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+(define_expand "nearbyintsf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:SF 1 "register_operand" ""))]
+ "TARGET_USE_FANCY_MATH_387
+ && (!TARGET_SSE_MATH || TARGET_MIX_SSE_I387)
+ && flag_unsafe_math_optimizations"
+{
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_frndintxf2_mask_pm (op0, op1));
+
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
+ DONE;
+})
+
+
;; Block operation instructions
(define_insn "cld"
- [(set (reg:SI 19) (const_int 0))]
+ [(set (reg:SI DIRFLAG_REG) (const_int 0))]
""
"cld"
[(set_attr "type" "cld")])
-(define_expand "movstrsi"
+(define_expand "movmemsi"
[(use (match_operand:BLK 0 "memory_operand" ""))
(use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "nonmemory_operand" ""))
(use (match_operand:SI 3 "const_int_operand" ""))]
- "! optimize_size"
+ "! optimize_size || TARGET_INLINE_ALL_STRINGOPS"
{
- if (ix86_expand_movstr (operands[0], operands[1], operands[2], operands[3]))
+ if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
DONE;
else
FAIL;
})
-(define_expand "movstrdi"
+(define_expand "movmemdi"
[(use (match_operand:BLK 0 "memory_operand" ""))
(use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:DI 2 "nonmemory_operand" ""))
(use (match_operand:DI 3 "const_int_operand" ""))]
"TARGET_64BIT"
{
- if (ix86_expand_movstr (operands[0], operands[1], operands[2], operands[3]))
+ if (ix86_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
DONE;
else
FAIL;
@@ -15415,9 +18025,9 @@
[(set (match_dup 4) (match_operand 3 "memory_operand" ""))
(set (match_operand 1 "memory_operand" "") (match_dup 4))
(parallel [(set (match_operand 0 "register_operand" "") (match_dup 5))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(parallel [(set (match_operand 2 "register_operand" "") (match_dup 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
{
rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])));
@@ -15445,7 +18055,7 @@
(match_operand 4 "" ""))
(set (match_operand 2 "register_operand" "")
(match_operand 5 "" ""))
- (use (reg:SI 19))])]
+ (use (reg:SI DIRFLAG_REG))])]
"TARGET_SINGLE_STRINGOP || optimize_size"
"")
@@ -15458,7 +18068,7 @@
(set (match_operand:DI 1 "register_operand" "=S")
(plus:DI (match_dup 3)
(const_int 8)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"movsq"
[(set_attr "type" "str")
@@ -15474,7 +18084,7 @@
(set (match_operand:SI 1 "register_operand" "=S")
(plus:SI (match_dup 3)
(const_int 4)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"{movsl|movsd}"
[(set_attr "type" "str")
@@ -15490,7 +18100,7 @@
(set (match_operand:DI 1 "register_operand" "=S")
(plus:DI (match_dup 3)
(const_int 4)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"{movsl|movsd}"
[(set_attr "type" "str")
@@ -15506,7 +18116,7 @@
(set (match_operand:SI 1 "register_operand" "=S")
(plus:SI (match_dup 3)
(const_int 2)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"movsw"
[(set_attr "type" "str")
@@ -15522,7 +18132,7 @@
(set (match_operand:DI 1 "register_operand" "=S")
(plus:DI (match_dup 3)
(const_int 2)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"movsw"
[(set_attr "type" "str")
@@ -15538,7 +18148,7 @@
(set (match_operand:SI 1 "register_operand" "=S")
(plus:SI (match_dup 3)
(const_int 1)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"movsb"
[(set_attr "type" "str")
@@ -15554,7 +18164,7 @@
(set (match_operand:DI 1 "register_operand" "=S")
(plus:DI (match_dup 3)
(const_int 1)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"movsb"
[(set_attr "type" "str")
@@ -15570,7 +18180,7 @@
(set (match_operand 1 "memory_operand" "")
(match_operand 3 "memory_operand" ""))
(use (match_dup 4))
- (use (reg:SI 19))])]
+ (use (reg:SI DIRFLAG_REG))])]
""
"")
@@ -15586,7 +18196,7 @@
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
(use (match_dup 5))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT"
"{rep\;movsq|rep movsq}"
[(set_attr "type" "str")
@@ -15606,7 +18216,7 @@
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
(use (match_dup 5))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT"
"{rep\;movsl|rep movsd}"
[(set_attr "type" "str")
@@ -15626,7 +18236,7 @@
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
(use (match_dup 5))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT"
"{rep\;movsl|rep movsd}"
[(set_attr "type" "str")
@@ -15644,7 +18254,7 @@
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
(use (match_dup 5))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT"
"{rep\;movsb|rep movsb}"
[(set_attr "type" "str")
@@ -15662,7 +18272,7 @@
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
(use (match_dup 5))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT"
"{rep\;movsb|rep movsb}"
[(set_attr "type" "str")
@@ -15670,25 +18280,35 @@
(set_attr "memory" "both")
(set_attr "mode" "SI")])
-(define_expand "clrstrsi"
+(define_expand "setmemsi"
[(use (match_operand:BLK 0 "memory_operand" ""))
(use (match_operand:SI 1 "nonmemory_operand" ""))
- (use (match_operand 2 "const_int_operand" ""))]
+ (use (match_operand 2 "const_int_operand" ""))
+ (use (match_operand 3 "const_int_operand" ""))]
""
{
- if (ix86_expand_clrstr (operands[0], operands[1], operands[2]))
+ /* If value to set is not zero, use the library routine. */
+ if (operands[2] != const0_rtx)
+ FAIL;
+
+ if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
DONE;
else
FAIL;
})
-(define_expand "clrstrdi"
+(define_expand "setmemdi"
[(use (match_operand:BLK 0 "memory_operand" ""))
(use (match_operand:DI 1 "nonmemory_operand" ""))
- (use (match_operand 2 "const_int_operand" ""))]
+ (use (match_operand 2 "const_int_operand" ""))
+ (use (match_operand 3 "const_int_operand" ""))]
"TARGET_64BIT"
{
- if (ix86_expand_clrstr (operands[0], operands[1], operands[2]))
+ /* If value to set is not zero, use the library routine. */
+ if (operands[2] != const0_rtx)
+ FAIL;
+
+ if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
DONE;
else
FAIL;
@@ -15702,7 +18322,7 @@
(match_operand 2 "register_operand" ""))
(parallel [(set (match_operand 0 "register_operand" "")
(match_dup 3))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
{
if (GET_MODE (operands[1]) != GET_MODE (operands[2]))
@@ -15726,17 +18346,17 @@
(match_operand 2 "register_operand" ""))
(set (match_operand 0 "register_operand" "")
(match_operand 3 "" ""))
- (use (reg:SI 19))])]
+ (use (reg:SI DIRFLAG_REG))])]
"TARGET_SINGLE_STRINGOP || optimize_size"
"")
(define_insn "*strsetdi_rex_1"
- [(set (mem:SI (match_operand:DI 1 "register_operand" "0"))
- (match_operand:SI 2 "register_operand" "a"))
+ [(set (mem:DI (match_operand:DI 1 "register_operand" "0"))
+ (match_operand:DI 2 "register_operand" "a"))
(set (match_operand:DI 0 "register_operand" "=D")
(plus:DI (match_dup 1)
(const_int 8)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"stosq"
[(set_attr "type" "str")
@@ -15749,7 +18369,7 @@
(set (match_operand:SI 0 "register_operand" "=D")
(plus:SI (match_dup 1)
(const_int 4)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"{stosl|stosd}"
[(set_attr "type" "str")
@@ -15762,7 +18382,7 @@
(set (match_operand:DI 0 "register_operand" "=D")
(plus:DI (match_dup 1)
(const_int 4)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"{stosl|stosd}"
[(set_attr "type" "str")
@@ -15775,7 +18395,7 @@
(set (match_operand:SI 0 "register_operand" "=D")
(plus:SI (match_dup 1)
(const_int 2)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"stosw"
[(set_attr "type" "str")
@@ -15788,7 +18408,7 @@
(set (match_operand:DI 0 "register_operand" "=D")
(plus:DI (match_dup 1)
(const_int 2)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"stosw"
[(set_attr "type" "str")
@@ -15801,7 +18421,7 @@
(set (match_operand:SI 0 "register_operand" "=D")
(plus:SI (match_dup 1)
(const_int 1)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"stosb"
[(set_attr "type" "str")
@@ -15814,7 +18434,7 @@
(set (match_operand:DI 0 "register_operand" "=D")
(plus:DI (match_dup 1)
(const_int 1)))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
"stosb"
[(set_attr "type" "str")
@@ -15828,7 +18448,7 @@
(set (match_operand 2 "memory_operand" "") (const_int 0))
(use (match_operand 3 "register_operand" ""))
(use (match_dup 1))
- (use (reg:SI 19))])]
+ (use (reg:SI DIRFLAG_REG))])]
""
"")
@@ -15842,7 +18462,7 @@
(const_int 0))
(use (match_operand:DI 2 "register_operand" "a"))
(use (match_dup 4))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT"
"{rep\;stosq|rep stosq}"
[(set_attr "type" "str")
@@ -15860,7 +18480,7 @@
(const_int 0))
(use (match_operand:SI 2 "register_operand" "a"))
(use (match_dup 4))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT"
"{rep\;stosl|rep stosd}"
[(set_attr "type" "str")
@@ -15878,7 +18498,7 @@
(const_int 0))
(use (match_operand:SI 2 "register_operand" "a"))
(use (match_dup 4))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT"
"{rep\;stosl|rep stosd}"
[(set_attr "type" "str")
@@ -15895,7 +18515,7 @@
(const_int 0))
(use (match_operand:QI 2 "register_operand" "a"))
(use (match_dup 4))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"!TARGET_64BIT"
"{rep\;stosb|rep stosb}"
[(set_attr "type" "str")
@@ -15912,7 +18532,7 @@
(const_int 0))
(use (match_operand:QI 2 "register_operand" "a"))
(use (match_dup 4))
- (use (reg:SI 19))]
+ (use (reg:SI DIRFLAG_REG))]
"TARGET_64BIT"
"{rep\;stosb|rep stosb}"
[(set_attr "type" "str")
@@ -15920,7 +18540,7 @@
(set_attr "memory" "store")
(set_attr "mode" "QI")])
-(define_expand "cmpstrsi"
+(define_expand "cmpstrnsi"
[(set (match_operand:SI 0 "register_operand" "")
(compare:SI (match_operand:BLK 1 "general_operand" "")
(match_operand:BLK 2 "general_operand" "")))
@@ -15961,8 +18581,8 @@
emit_move_insn (operands[0], const0_rtx);
DONE;
}
- emit_insn (gen_cmpstrqi_nz_1 (addr1, addr2, countreg, align,
- operands[1], operands[2]));
+ emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align,
+ operands[1], operands[2]));
}
else
{
@@ -15970,8 +18590,8 @@
emit_insn (gen_cmpdi_1_rex64 (countreg, countreg));
else
emit_insn (gen_cmpsi_1 (countreg, countreg));
- emit_insn (gen_cmpstrqi_1 (addr1, addr2, countreg, align,
- operands[1], operands[2]));
+ emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
+ operands[1], operands[2]));
}
outlow = gen_lowpart (QImode, out);
@@ -15988,13 +18608,13 @@
(define_expand "cmpintqi"
[(set (match_dup 1)
- (gtu:QI (reg:CC 17) (const_int 0)))
+ (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
(set (match_dup 2)
- (ltu:QI (reg:CC 17) (const_int 0)))
+ (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
(parallel [(set (match_operand:QI 0 "register_operand" "")
(minus:QI (match_dup 1)
(match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"operands[1] = gen_reg_rtx (QImode);
operands[2] = gen_reg_rtx (QImode);")
@@ -16002,26 +18622,26 @@
;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is
;; zero. Emit extra code to make sure that a zero-length compare is EQ.
-(define_expand "cmpstrqi_nz_1"
- [(parallel [(set (reg:CC 17)
+(define_expand "cmpstrnqi_nz_1"
+ [(parallel [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand 4 "memory_operand" "")
(match_operand 5 "memory_operand" "")))
(use (match_operand 2 "register_operand" ""))
(use (match_operand:SI 3 "immediate_operand" ""))
- (use (reg:SI 19))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand 0 "register_operand" ""))
(clobber (match_operand 1 "register_operand" ""))
(clobber (match_dup 2))])]
""
"")
-(define_insn "*cmpstrqi_nz_1"
- [(set (reg:CC 17)
+(define_insn "*cmpstrnqi_nz_1"
+ [(set (reg:CC FLAGS_REG)
(compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
(mem:BLK (match_operand:SI 5 "register_operand" "1"))))
(use (match_operand:SI 6 "register_operand" "2"))
(use (match_operand:SI 3 "immediate_operand" "i"))
- (use (reg:SI 19))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand:SI 0 "register_operand" "=S"))
(clobber (match_operand:SI 1 "register_operand" "=D"))
(clobber (match_operand:SI 2 "register_operand" "=c"))]
@@ -16031,13 +18651,13 @@
(set_attr "mode" "QI")
(set_attr "prefix_rep" "1")])
-(define_insn "*cmpstrqi_nz_rex_1"
- [(set (reg:CC 17)
+(define_insn "*cmpstrnqi_nz_rex_1"
+ [(set (reg:CC FLAGS_REG)
(compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
(mem:BLK (match_operand:DI 5 "register_operand" "1"))))
(use (match_operand:DI 6 "register_operand" "2"))
(use (match_operand:SI 3 "immediate_operand" "i"))
- (use (reg:SI 19))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand:DI 0 "register_operand" "=S"))
(clobber (match_operand:DI 1 "register_operand" "=D"))
(clobber (match_operand:DI 2 "register_operand" "=c"))]
@@ -16049,32 +18669,32 @@
;; The same, but the count is not known to not be zero.
-(define_expand "cmpstrqi_1"
- [(parallel [(set (reg:CC 17)
+(define_expand "cmpstrnqi_1"
+ [(parallel [(set (reg:CC FLAGS_REG)
(if_then_else:CC (ne (match_operand 2 "register_operand" "")
(const_int 0))
(compare:CC (match_operand 4 "memory_operand" "")
(match_operand 5 "memory_operand" ""))
(const_int 0)))
(use (match_operand:SI 3 "immediate_operand" ""))
- (use (reg:CC 17))
- (use (reg:SI 19))
+ (use (reg:CC FLAGS_REG))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand 0 "register_operand" ""))
(clobber (match_operand 1 "register_operand" ""))
(clobber (match_dup 2))])]
""
"")
-(define_insn "*cmpstrqi_1"
- [(set (reg:CC 17)
+(define_insn "*cmpstrnqi_1"
+ [(set (reg:CC FLAGS_REG)
(if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
(const_int 0))
(compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
(mem:BLK (match_operand:SI 5 "register_operand" "1")))
(const_int 0)))
(use (match_operand:SI 3 "immediate_operand" "i"))
- (use (reg:CC 17))
- (use (reg:SI 19))
+ (use (reg:CC FLAGS_REG))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand:SI 0 "register_operand" "=S"))
(clobber (match_operand:SI 1 "register_operand" "=D"))
(clobber (match_operand:SI 2 "register_operand" "=c"))]
@@ -16084,16 +18704,16 @@
(set_attr "mode" "QI")
(set_attr "prefix_rep" "1")])
-(define_insn "*cmpstrqi_rex_1"
- [(set (reg:CC 17)
+(define_insn "*cmpstrnqi_rex_1"
+ [(set (reg:CC FLAGS_REG)
(if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2")
(const_int 0))
(compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0"))
(mem:BLK (match_operand:DI 5 "register_operand" "1")))
(const_int 0)))
(use (match_operand:SI 3 "immediate_operand" "i"))
- (use (reg:CC 17))
- (use (reg:SI 19))
+ (use (reg:CC FLAGS_REG))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand:DI 0 "register_operand" "=S"))
(clobber (match_operand:DI 1 "register_operand" "=D"))
(clobber (match_operand:DI 2 "register_operand" "=c"))]
@@ -16131,9 +18751,9 @@
(define_expand "strlenqi_1"
[(parallel [(set (match_operand 0 "register_operand" "") (match_operand 2 "" ""))
- (use (reg:SI 19))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand 1 "register_operand" ""))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
@@ -16143,9 +18763,9 @@
(match_operand:QI 2 "register_operand" "a")
(match_operand:SI 3 "immediate_operand" "i")
(match_operand:SI 4 "register_operand" "0")] UNSPEC_SCAS))
- (use (reg:SI 19))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand:SI 1 "register_operand" "=D"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
"repnz{\;| }scasb"
[(set_attr "type" "str")
@@ -16158,18 +18778,18 @@
(match_operand:QI 2 "register_operand" "a")
(match_operand:DI 3 "immediate_operand" "i")
(match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS))
- (use (reg:SI 19))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand:DI 1 "register_operand" "=D"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"repnz{\;| }scasb"
[(set_attr "type" "str")
(set_attr "mode" "QI")
(set_attr "prefix_rep" "1")])
-;; Peephole optimizations to clean up after cmpstr*. This should be
+;; Peephole optimizations to clean up after cmpstrn*. This should be
;; handled in combine, but it is not currently up to the task.
-;; When used for their truth value, the cmpstr* expanders generate
+;; When used for their truth value, the cmpstrn* expanders generate
;; code like this:
;;
;; repz cmpsb
@@ -16180,71 +18800,71 @@
;;
;; The intermediate three instructions are unnecessary.
-;; This one handles cmpstr*_nz_1...
+;; This one handles cmpstrn*_nz_1...
(define_peephole2
[(parallel[
- (set (reg:CC 17)
+ (set (reg:CC FLAGS_REG)
(compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
(mem:BLK (match_operand 5 "register_operand" ""))))
(use (match_operand 6 "register_operand" ""))
(use (match_operand:SI 3 "immediate_operand" ""))
- (use (reg:SI 19))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand 0 "register_operand" ""))
(clobber (match_operand 1 "register_operand" ""))
(clobber (match_operand 2 "register_operand" ""))])
(set (match_operand:QI 7 "register_operand" "")
- (gtu:QI (reg:CC 17) (const_int 0)))
+ (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
(set (match_operand:QI 8 "register_operand" "")
- (ltu:QI (reg:CC 17) (const_int 0)))
- (set (reg 17)
+ (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
+ (set (reg FLAGS_REG)
(compare (match_dup 7) (match_dup 8)))
]
"peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
[(parallel[
- (set (reg:CC 17)
+ (set (reg:CC FLAGS_REG)
(compare:CC (mem:BLK (match_dup 4))
(mem:BLK (match_dup 5))))
(use (match_dup 6))
(use (match_dup 3))
- (use (reg:SI 19))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_dup 0))
(clobber (match_dup 1))
(clobber (match_dup 2))])]
"")
-;; ...and this one handles cmpstr*_1.
+;; ...and this one handles cmpstrn*_1.
(define_peephole2
[(parallel[
- (set (reg:CC 17)
+ (set (reg:CC FLAGS_REG)
(if_then_else:CC (ne (match_operand 6 "register_operand" "")
(const_int 0))
(compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
(mem:BLK (match_operand 5 "register_operand" "")))
(const_int 0)))
(use (match_operand:SI 3 "immediate_operand" ""))
- (use (reg:CC 17))
- (use (reg:SI 19))
+ (use (reg:CC FLAGS_REG))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_operand 0 "register_operand" ""))
(clobber (match_operand 1 "register_operand" ""))
(clobber (match_operand 2 "register_operand" ""))])
(set (match_operand:QI 7 "register_operand" "")
- (gtu:QI (reg:CC 17) (const_int 0)))
+ (gtu:QI (reg:CC FLAGS_REG) (const_int 0)))
(set (match_operand:QI 8 "register_operand" "")
- (ltu:QI (reg:CC 17) (const_int 0)))
- (set (reg 17)
+ (ltu:QI (reg:CC FLAGS_REG) (const_int 0)))
+ (set (reg FLAGS_REG)
(compare (match_dup 7) (match_dup 8)))
]
"peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
[(parallel[
- (set (reg:CC 17)
+ (set (reg:CC FLAGS_REG)
(if_then_else:CC (ne (match_dup 6)
(const_int 0))
(compare:CC (mem:BLK (match_dup 4))
(mem:BLK (match_dup 5)))
(const_int 0)))
(use (match_dup 3))
- (use (reg:CC 17))
- (use (reg:SI 19))
+ (use (reg:CC FLAGS_REG))
+ (use (reg:SI DIRFLAG_REG))
(clobber (match_dup 0))
(clobber (match_dup 1))
(clobber (match_dup 2))])]
@@ -16267,7 +18887,7 @@
(if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "")
(const_int -1)
(const_int 0)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"sbb{q}\t%0, %0"
; Since we don't have the proper number of operands for an alu insn,
@@ -16279,10 +18899,10 @@
(set_attr "mode" "DI")
(set_attr "length_immediate" "0")])
-(define_insn "movdicc_c_rex64"
+(define_insn "*movdicc_c_rex64"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(if_then_else:DI (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(match_operand:DI 2 "nonimmediate_operand" "rm,0")
(match_operand:DI 3 "nonimmediate_operand" "0,rm")))]
"TARGET_64BIT && TARGET_CMOVE
@@ -16310,7 +18930,7 @@
(if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "")
(const_int -1)
(const_int 0)))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
""
"sbb{l}\t%0, %0"
; Since we don't have the proper number of operands for an alu insn,
@@ -16325,7 +18945,7 @@
(define_insn "*movsicc_noc"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(if_then_else:SI (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(match_operand:SI 2 "nonimmediate_operand" "rm,0")
(match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
"TARGET_CMOVE
@@ -16347,7 +18967,7 @@
(define_insn "*movhicc_noc"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(if_then_else:HI (match_operator 1 "ix86_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(match_operand:HI 2 "nonimmediate_operand" "rm,0")
(match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
"TARGET_CMOVE
@@ -16369,7 +18989,8 @@
(define_insn_and_split "*movqicc_noc"
[(set (match_operand:QI 0 "register_operand" "=r,r")
(if_then_else:QI (match_operator 1 "ix86_comparison_operator"
- [(match_operand 4 "flags_reg_operand" "") (const_int 0)])
+ [(match_operand 4 "flags_reg_operand" "")
+ (const_int 0)])
(match_operand:QI 2 "register_operand" "r,0")
(match_operand:QI 3 "register_operand" "0,r")))]
"TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL"
@@ -16390,16 +19011,16 @@
(if_then_else:SF (match_operand 1 "comparison_operator" "")
(match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "register_operand" "")))]
- "TARGET_CMOVE"
+ "(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
-(define_insn "*movsfcc_1"
- [(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f")
+(define_insn "*movsfcc_1_387"
+ [(set (match_operand:SF 0 "register_operand" "=f,f,r,r")
(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
- [(reg 17) (const_int 0)])
- (match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
- (match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
- "TARGET_CMOVE
+ [(reg FLAGS_REG) (const_int 0)])
+ (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0")
+ (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))]
+ "TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@
fcmov%F1\t{%2, %0|%0, %2}
@@ -16414,16 +19035,16 @@
(if_then_else:DF (match_operand 1 "comparison_operator" "")
(match_operand:DF 2 "register_operand" "")
(match_operand:DF 3 "register_operand" "")))]
- "TARGET_CMOVE"
+ "(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
(define_insn "*movdfcc_1"
- [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f")
+ [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
- [(reg 17) (const_int 0)])
- (match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
- (match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
- "!TARGET_64BIT && TARGET_CMOVE
+ [(reg FLAGS_REG) (const_int 0)])
+ (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
+ (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
+ "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@
fcmov%F1\t{%2, %0|%0, %2}
@@ -16434,12 +19055,12 @@
(set_attr "mode" "DF")])
(define_insn "*movdfcc_1_rex64"
- [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,r#f,r#f")
+ [(set (match_operand:DF 0 "register_operand" "=f,f,r,r")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
- [(reg 17) (const_int 0)])
- (match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f")
- (match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))]
- "TARGET_64BIT && TARGET_CMOVE
+ [(reg FLAGS_REG) (const_int 0)])
+ (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0")
+ (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))]
+ "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@
fcmov%F1\t{%2, %0|%0, %2}
@@ -16452,7 +19073,8 @@
(define_split
[(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
- [(match_operand 4 "flags_reg_operand" "") (const_int 0)])
+ [(match_operand 4 "flags_reg_operand" "")
+ (const_int 0)])
(match_operand:DF 2 "nonimmediate_operand" "")
(match_operand:DF 3 "nonimmediate_operand" "")))]
"!TARGET_64BIT && reload_completed"
@@ -16473,71 +19095,134 @@
(if_then_else:XF (match_operand 1 "comparison_operator" "")
(match_operand:XF 2 "register_operand" "")
(match_operand:XF 3 "register_operand" "")))]
- "TARGET_CMOVE"
+ "TARGET_80387 && TARGET_CMOVE"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
(define_insn "*movxfcc_1"
[(set (match_operand:XF 0 "register_operand" "=f,f")
(if_then_else:XF (match_operator 1 "fcmov_comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(match_operand:XF 2 "register_operand" "f,0")
(match_operand:XF 3 "register_operand" "0,f")))]
- "TARGET_CMOVE"
+ "TARGET_80387 && TARGET_CMOVE"
"@
fcmov%F1\t{%2, %0|%0, %2}
fcmov%f1\t{%3, %0|%0, %3}"
[(set_attr "type" "fcmov")
(set_attr "mode" "XF")])
-(define_expand "minsf3"
- [(parallel [
- (set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "nonimmediate_operand" ""))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))])]
- "TARGET_SSE"
- "")
+;; These versions of the min/max patterns are intentionally ignorant of
+;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
+;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
+;; are undefined in this condition, we're certain this is correct.
-(define_insn "*minsf"
- [(set (match_operand:SF 0 "register_operand" "=x#f,f#x,f#x")
- (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "0,0,f#x")
- (match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x,0"))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "TARGET_SSE && TARGET_IEEE_FP"
- "#")
+(define_insn "sminsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
+ (match_operand:SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE_MATH"
+ "minss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
-(define_insn "*minsf_nonieee"
- [(set (match_operand:SF 0 "register_operand" "=x#f,f#x")
- (if_then_else:SF (lt (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x"))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "TARGET_SSE && !TARGET_IEEE_FP
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "#")
+(define_insn "smaxsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
+ (match_operand:SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE_MATH"
+ "maxss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "nonimmediate_operand" ""))
- (match_operand:SF 3 "register_operand" "")
- (match_operand:SF 4 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed
- && ((operands_match_p (operands[1], operands[3])
- && operands_match_p (operands[2], operands[4]))
- || (operands_match_p (operands[1], operands[4])
- && operands_match_p (operands[2], operands[3])))"
- [(set (match_dup 0)
- (if_then_else:SF (lt (match_dup 1)
- (match_dup 2))
- (match_dup 1)
- (match_dup 2)))])
+(define_insn "smindf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
+ (match_operand:DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "minsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_insn "smaxdf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
+ (match_operand:DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "maxsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+;; These versions of the min/max patterns implement exactly the operations
+;; min = (op1 < op2 ? op1 : op2)
+;; max = (!(op1 < op2) ? op1 : op2)
+;; Their operands are not commutative, and thus they may be used in the
+;; presence of -0.0 and NaN.
+
+(define_insn "*ieee_sminsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (unspec:SF [(match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "nonimmediate_operand" "xm")]
+ UNSPEC_IEEE_MIN))]
+ "TARGET_SSE_MATH"
+ "minss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
+
+(define_insn "*ieee_smaxsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (unspec:SF [(match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "nonimmediate_operand" "xm")]
+ UNSPEC_IEEE_MAX))]
+ "TARGET_SSE_MATH"
+ "maxss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
+
+(define_insn "*ieee_smindf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (unspec:DF [(match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "nonimmediate_operand" "xm")]
+ UNSPEC_IEEE_MIN))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "minsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_insn "*ieee_smaxdf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (unspec:DF [(match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "nonimmediate_operand" "xm")]
+ UNSPEC_IEEE_MAX))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "maxsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+;; Make two stack loads independent:
+;; fld aa fld aa
+;; fld %st(0) -> fld bb
+;; fmul bb fmul %st(1), %st
+;;
+;; Actually we only match the last two instructions for simplicity.
+(define_peephole2
+ [(set (match_operand 0 "fp_register_operand" "")
+ (match_operand 1 "fp_register_operand" ""))
+ (set (match_dup 0)
+ (match_operator 2 "binary_fp_operator"
+ [(match_dup 0)
+ (match_operand 3 "memory_operand" "")]))]
+ "REGNO (operands[0]) != REGNO (operands[1])"
+ [(set (match_dup 0) (match_dup 3))
+ (set (match_dup 0) (match_dup 4))]
+
+ ;; The % modifier is not operational anymore in peephole2's, so we have to
+ ;; swap the operands manually in the case of addition and multiplication.
+ "if (COMMUTATIVE_ARITH_P (operands[2]))
+ operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
+ operands[0], operands[1]);
+ else
+ operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
+ operands[1], operands[0]);")
;; Conditional addition patterns
(define_expand "addqicc"
@@ -16572,282 +19257,6 @@
"TARGET_64BIT"
"if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
-;; We can't represent the LT test directly. Do this by swapping the operands.
-
-(define_split
- [(set (match_operand:SF 0 "fp_register_operand" "")
- (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "register_operand" ""))
- (match_operand:SF 3 "register_operand" "")
- (match_operand:SF 4 "register_operand" "")))
- (clobber (reg:CC 17))]
- "reload_completed
- && ((operands_match_p (operands[1], operands[3])
- && operands_match_p (operands[2], operands[4]))
- || (operands_match_p (operands[1], operands[4])
- && operands_match_p (operands[2], operands[3])))"
- [(set (reg:CCFP 17)
- (compare:CCFP (match_dup 2)
- (match_dup 1)))
- (set (match_dup 0)
- (if_then_else:SF (ge (reg:CCFP 17) (const_int 0))
- (match_dup 1)
- (match_dup 2)))])
-
-(define_insn "*minsf_sse"
- [(set (match_operand:SF 0 "register_operand" "=x")
- (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "0")
- (match_operand:SF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_SSE && reload_completed"
- "minss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
- (set_attr "mode" "SF")])
-
-(define_expand "mindf3"
- [(parallel [
- (set (match_operand:DF 0 "register_operand" "")
- (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "nonimmediate_operand" ""))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))])]
- "TARGET_SSE2 && TARGET_SSE_MATH"
- "#")
-
-(define_insn "*mindf"
- [(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y,f#Y")
- (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "0,0,f#Y")
- (match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y,0"))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "TARGET_SSE2 && TARGET_IEEE_FP && TARGET_SSE_MATH"
- "#")
-
-(define_insn "*mindf_nonieee"
- [(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y")
- (if_then_else:DF (lt (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y"))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_IEEE_FP
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "#")
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "nonimmediate_operand" ""))
- (match_operand:DF 3 "register_operand" "")
- (match_operand:DF 4 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed
- && ((operands_match_p (operands[1], operands[3])
- && operands_match_p (operands[2], operands[4]))
- || (operands_match_p (operands[1], operands[4])
- && operands_match_p (operands[2], operands[3])))"
- [(set (match_dup 0)
- (if_then_else:DF (lt (match_dup 1)
- (match_dup 2))
- (match_dup 1)
- (match_dup 2)))])
-
-;; We can't represent the LT test directly. Do this by swapping the operands.
-(define_split
- [(set (match_operand:DF 0 "fp_register_operand" "")
- (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "register_operand" ""))
- (match_operand:DF 3 "register_operand" "")
- (match_operand:DF 4 "register_operand" "")))
- (clobber (reg:CC 17))]
- "reload_completed
- && ((operands_match_p (operands[1], operands[3])
- && operands_match_p (operands[2], operands[4]))
- || (operands_match_p (operands[1], operands[4])
- && operands_match_p (operands[2], operands[3])))"
- [(set (reg:CCFP 17)
- (compare:CCFP (match_dup 2)
- (match_dup 1)))
- (set (match_dup 0)
- (if_then_else:DF (ge (reg:CCFP 17) (const_int 0))
- (match_dup 1)
- (match_dup 2)))])
-
-(define_insn "*mindf_sse"
- [(set (match_operand:DF 0 "register_operand" "=Y")
- (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "0")
- (match_operand:DF 2 "nonimmediate_operand" "Ym"))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
- "minsd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
- (set_attr "mode" "DF")])
-
-(define_expand "maxsf3"
- [(parallel [
- (set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "nonimmediate_operand" ""))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))])]
- "TARGET_SSE"
- "#")
-
-(define_insn "*maxsf"
- [(set (match_operand:SF 0 "register_operand" "=x#f,f#x,f#x")
- (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "0,0,f#x")
- (match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x,0"))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "TARGET_SSE && TARGET_IEEE_FP"
- "#")
-
-(define_insn "*maxsf_nonieee"
- [(set (match_operand:SF 0 "register_operand" "=x#f,f#x")
- (if_then_else:SF (gt (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x"))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "TARGET_SSE && !TARGET_IEEE_FP
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "#")
-
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "nonimmediate_operand" ""))
- (match_operand:SF 3 "register_operand" "")
- (match_operand:SF 4 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed
- && ((operands_match_p (operands[1], operands[3])
- && operands_match_p (operands[2], operands[4]))
- || (operands_match_p (operands[1], operands[4])
- && operands_match_p (operands[2], operands[3])))"
- [(set (match_dup 0)
- (if_then_else:SF (gt (match_dup 1)
- (match_dup 2))
- (match_dup 1)
- (match_dup 2)))])
-
-(define_split
- [(set (match_operand:SF 0 "fp_register_operand" "")
- (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "register_operand" ""))
- (match_operand:SF 3 "register_operand" "")
- (match_operand:SF 4 "register_operand" "")))
- (clobber (reg:CC 17))]
- "reload_completed
- && ((operands_match_p (operands[1], operands[3])
- && operands_match_p (operands[2], operands[4]))
- || (operands_match_p (operands[1], operands[4])
- && operands_match_p (operands[2], operands[3])))"
- [(set (reg:CCFP 17)
- (compare:CCFP (match_dup 1)
- (match_dup 2)))
- (set (match_dup 0)
- (if_then_else:SF (gt (reg:CCFP 17) (const_int 0))
- (match_dup 1)
- (match_dup 2)))])
-
-(define_insn "*maxsf_sse"
- [(set (match_operand:SF 0 "register_operand" "=x")
- (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "0")
- (match_operand:SF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_SSE && reload_completed"
- "maxss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
- (set_attr "mode" "SF")])
-
-(define_expand "maxdf3"
- [(parallel [
- (set (match_operand:DF 0 "register_operand" "")
- (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "nonimmediate_operand" ""))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))])]
- "TARGET_SSE2 && TARGET_SSE_MATH"
- "#")
-
-(define_insn "*maxdf"
- [(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y,f#Y")
- (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "0,0,f#Y")
- (match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y,0"))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_IEEE_FP"
- "#")
-
-(define_insn "*maxdf_nonieee"
- [(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y")
- (if_then_else:DF (gt (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y"))
- (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC 17))]
- "TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_IEEE_FP
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "#")
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "nonimmediate_operand" ""))
- (match_operand:DF 3 "register_operand" "")
- (match_operand:DF 4 "nonimmediate_operand" "")))
- (clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed
- && ((operands_match_p (operands[1], operands[3])
- && operands_match_p (operands[2], operands[4]))
- || (operands_match_p (operands[1], operands[4])
- && operands_match_p (operands[2], operands[3])))"
- [(set (match_dup 0)
- (if_then_else:DF (gt (match_dup 1)
- (match_dup 2))
- (match_dup 1)
- (match_dup 2)))])
-
-(define_split
- [(set (match_operand:DF 0 "fp_register_operand" "")
- (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
- (match_operand:DF 2 "register_operand" ""))
- (match_operand:DF 3 "register_operand" "")
- (match_operand:DF 4 "register_operand" "")))
- (clobber (reg:CC 17))]
- "reload_completed
- && ((operands_match_p (operands[1], operands[3])
- && operands_match_p (operands[2], operands[4]))
- || (operands_match_p (operands[1], operands[4])
- && operands_match_p (operands[2], operands[3])))"
- [(set (reg:CCFP 17)
- (compare:CCFP (match_dup 1)
- (match_dup 2)))
- (set (match_dup 0)
- (if_then_else:DF (gt (reg:CCFP 17) (const_int 0))
- (match_dup 1)
- (match_dup 2)))])
-
-(define_insn "*maxdf_sse"
- [(set (match_operand:DF 0 "register_operand" "=Y")
- (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "0")
- (match_operand:DF 2 "nonimmediate_operand" "Ym"))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
- "maxsd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
- (set_attr "mode" "DF")])
;; Misc patterns (?)
@@ -16864,7 +19273,7 @@
[(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_operand:SI 1 "register_operand" "0,r")
(match_operand:SI 2 "immediate_operand" "i,i")))
- (clobber (reg:CC 17))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))]
"!TARGET_64BIT"
{
@@ -16889,7 +19298,7 @@
return "lea{l}\t{%a2, %0|%0, %a2}";
default:
- abort ();
+ gcc_unreachable ();
}
}
[(set (attr "type")
@@ -16905,7 +19314,7 @@
[(set (match_operand:DI 0 "register_operand" "=r,r")
(plus:DI (match_operand:DI 1 "register_operand" "0,r")
(match_operand:DI 2 "x86_64_immediate_operand" "e,e")))
- (clobber (reg:CC 17))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))]
"TARGET_64BIT"
{
@@ -16932,7 +19341,7 @@
return "lea{q}\t{%a2, %0|%0, %a2}";
default:
- abort ();
+ gcc_unreachable ();
}
}
[(set (attr "type")
@@ -16949,7 +19358,7 @@
(plus:DI (match_operand:DI 1 "register_operand" "0,r")
(match_operand:DI 3 "immediate_operand" "i,i")))
(use (match_operand:DI 2 "register_operand" "r,r"))
- (clobber (reg:CC 17))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))]
"TARGET_64BIT"
{
@@ -16963,372 +19372,12 @@
return "lea{q}\t{%a2, %0|%0, %a2}";
default:
- abort ();
+ gcc_unreachable ();
}
}
[(set_attr "type" "alu,lea")
(set_attr "mode" "DI")])
-;; Placeholder for the conditional moves. This one is split either to SSE
-;; based moves emulation or to usual cmove sequence. Little bit unfortunate
-;; fact is that compares supported by the cmp??ss instructions are exactly
-;; swapped of those supported by cmove sequence.
-;; The EQ/NE comparisons also needs bit care, since they are not directly
-;; supported by i387 comparisons and we do need to emit two conditional moves
-;; in tandem.
-
-(define_insn "sse_movsfcc"
- [(set (match_operand:SF 0 "register_operand" "=&x#rf,x#rf,?f#xr,?f#xr,?f#xr,?f#xr,?r#xf,?r#xf,?r#xf,?r#xf")
- (if_then_else:SF (match_operator 1 "sse_comparison_operator"
- [(match_operand:SF 4 "nonimmediate_operand" "0#fx,x#fx,f#x,f#x,xm#f,xm#f,f#x,f#x,xm#f,xm#f")
- (match_operand:SF 5 "nonimmediate_operand" "xm#f,xm#f,f#x,f#x,x#f,x#f,f#x,f#x,x#f,x#f")])
- (match_operand:SF 2 "nonimmediate_operand" "x#fr,0#fr,f#fx,0#fx,f#fx,0#fx,rm#rx,0#rx,rm#rx,0#rx")
- (match_operand:SF 3 "nonimmediate_operand" "x#fr,x#fr,0#fx,f#fx,0#fx,f#fx,0#fx,rm#rx,0#rx,rm#rx")))
- (clobber (match_scratch:SF 6 "=2,&4,X,X,X,X,X,X,X,X"))
- (clobber (reg:CC 17))]
- "TARGET_SSE
- && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)
- /* Avoid combine from being smart and converting min/max
- instruction patterns into conditional moves. */
- && ((GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != GT
- && GET_CODE (operands[1]) != UNLE && GET_CODE (operands[1]) != UNGE)
- || !rtx_equal_p (operands[4], operands[2])
- || !rtx_equal_p (operands[5], operands[3]))
- && (!TARGET_IEEE_FP
- || (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE))"
- "#")
-
-(define_insn "sse_movsfcc_eq"
- [(set (match_operand:SF 0 "register_operand" "=&x#rf,x#rf,?f#xr,?f#xr,?r#xf,?r#xf")
- (if_then_else:SF (eq (match_operand:SF 3 "nonimmediate_operand" "%0#fx,x#fx,f#x,xm#f,f#x,xm#f")
- (match_operand:SF 4 "nonimmediate_operand" "xm#f,xm#f,f#x,x#f,f#x,x#f"))
- (match_operand:SF 1 "nonimmediate_operand" "x#fr,0#fr,0#fx,0#fx,0#rx,0#rx")
- (match_operand:SF 2 "nonimmediate_operand" "x#fr,x#fr,f#fx,f#fx,rm#rx,rm#rx")))
- (clobber (match_scratch:SF 5 "=1,&3,X,X,X,X"))
- (clobber (reg:CC 17))]
- "TARGET_SSE
- && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
- "#")
-
-(define_insn "sse_movdfcc"
- [(set (match_operand:DF 0 "register_operand" "=&Y#rf,Y#rf,?f#Yr,?f#Yr,?f#Yr,?f#Yr,?r#Yf,?r#Yf,?r#Yf,?r#Yf")
- (if_then_else:DF (match_operator 1 "sse_comparison_operator"
- [(match_operand:DF 4 "nonimmediate_operand" "0#fY,Y#fY,f#Y,f#Y,Ym#f,Ym#f,f#Y,f#Y,Ym#f,Ym#f")
- (match_operand:DF 5 "nonimmediate_operand" "Ym#f,Ym#f,f#Y,f#Y,Y#f,Y#f,f#Y,f#Y,Y#f,Y#f")])
- (match_operand:DF 2 "nonimmediate_operand" "Y#fr,0#fr,f#fY,0#fY,f#fY,0#fY,rm#rY,0#rY,rm#rY,0#rY")
- (match_operand:DF 3 "nonimmediate_operand" "Y#fr,Y#fr,0#fY,f#fY,0#fY,f#fY,0#fY,rm#rY,0#rY,rm#rY")))
- (clobber (match_scratch:DF 6 "=2,&4,X,X,X,X,X,X,X,X"))
- (clobber (reg:CC 17))]
- "TARGET_SSE2
- && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)
- /* Avoid combine from being smart and converting min/max
- instruction patterns into conditional moves. */
- && ((GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != GT
- && GET_CODE (operands[1]) != UNLE && GET_CODE (operands[1]) != UNGE)
- || !rtx_equal_p (operands[4], operands[2])
- || !rtx_equal_p (operands[5], operands[3]))
- && (!TARGET_IEEE_FP
- || (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE))"
- "#")
-
-(define_insn "sse_movdfcc_eq"
- [(set (match_operand:DF 0 "register_operand" "=&Y#rf,Y#rf,?f#Yr,?f#Yr,?r#Yf,?r#Yf")
- (if_then_else:DF (eq (match_operand:DF 3 "nonimmediate_operand" "%0#fY,Y#fY,f#Y,Ym#f,f#Y,Ym#f")
- (match_operand:DF 4 "nonimmediate_operand" "Ym#f,Ym#f,f#Y,Y#f,f#Y,Y#f"))
- (match_operand:DF 1 "nonimmediate_operand" "Y#fr,0#fr,0#fY,0#fY,0#rY,0#rY")
- (match_operand:DF 2 "nonimmediate_operand" "Y#fr,Y#fr,f#fY,f#fY,rm#rY,rm#rY")))
- (clobber (match_scratch:DF 5 "=1,&3,X,X,X,X"))
- (clobber (reg:CC 17))]
- "TARGET_SSE
- && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
- "#")
-
-;; For non-sse moves just expand the usual cmove sequence.
-(define_split
- [(set (match_operand 0 "register_operand" "")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand 4 "nonimmediate_operand" "")
- (match_operand 5 "register_operand" "")])
- (match_operand 2 "nonimmediate_operand" "")
- (match_operand 3 "nonimmediate_operand" "")))
- (clobber (match_operand 6 "" ""))
- (clobber (reg:CC 17))]
- "!SSE_REG_P (operands[0]) && reload_completed
- && (GET_MODE (operands[0]) == SFmode
- || (TARGET_SSE2 && GET_MODE (operands[0]) == DFmode))"
- [(const_int 0)]
-{
- ix86_compare_op0 = operands[5];
- ix86_compare_op1 = operands[4];
- operands[1] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])),
- VOIDmode, operands[5], operands[4]);
- ix86_expand_fp_movcc (operands);
- DONE;
-})
-
-;; Split SSE based conditional move into sequence:
-;; cmpCC op0, op4 - set op0 to 0 or ffffffff depending on the comparison
-;; and op2, op0 - zero op2 if comparison was false
-;; nand op0, op3 - load op3 to op0 if comparison was false
-;; or op2, op0 - get the nonzero one into the result.
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (match_operator 1 "sse_comparison_operator"
- [(match_operand:SF 4 "register_operand" "")
- (match_operand:SF 5 "nonimmediate_operand" "")])
- (match_operand:SF 2 "register_operand" "")
- (match_operand:SF 3 "register_operand" "")))
- (clobber (match_operand 6 "" ""))
- (clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed"
- [(set (match_dup 4) (match_op_dup 1 [(match_dup 4) (match_dup 5)]))
- (set (match_dup 2) (and:V4SF (match_dup 2)
- (match_dup 8)))
- (set (match_dup 8) (and:V4SF (not:V4SF (match_dup 8))
- (match_dup 3)))
- (set (match_dup 0) (ior:V4SF (match_dup 6)
- (match_dup 7)))]
-{
- /* If op2 == op3, op3 would be clobbered before it is used. */
- if (operands_match_p (operands[2], operands[3]))
- {
- emit_move_insn (operands[0], operands[2]);
- DONE;
- }
-
- PUT_MODE (operands[1], GET_MODE (operands[0]));
- if (operands_match_p (operands[0], operands[4]))
- operands[6] = operands[4], operands[7] = operands[2];
- else
- operands[6] = operands[2], operands[7] = operands[4];
- operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
- operands[2] = simplify_gen_subreg (V4SFmode, operands[2], SFmode, 0);
- operands[3] = simplify_gen_subreg (V4SFmode, operands[3], SFmode, 0);
- operands[8] = simplify_gen_subreg (V4SFmode, operands[4], SFmode, 0);
- operands[6] = simplify_gen_subreg (V4SFmode, operands[6], SFmode, 0);
- operands[7] = simplify_gen_subreg (V4SFmode, operands[7], SFmode, 0);
-})
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (if_then_else:DF (match_operator 1 "sse_comparison_operator"
- [(match_operand:DF 4 "register_operand" "")
- (match_operand:DF 5 "nonimmediate_operand" "")])
- (match_operand:DF 2 "register_operand" "")
- (match_operand:DF 3 "register_operand" "")))
- (clobber (match_operand 6 "" ""))
- (clobber (reg:CC 17))]
- "SSE_REG_P (operands[0]) && reload_completed"
- [(set (match_dup 4) (match_op_dup 1 [(match_dup 4) (match_dup 5)]))
- (set (match_dup 2) (and:V2DF (match_dup 2)
- (match_dup 8)))
- (set (match_dup 8) (and:V2DF (not:V2DF (match_dup 8))
- (match_dup 3)))
- (set (match_dup 0) (ior:V2DF (match_dup 6)
- (match_dup 7)))]
-{
- if (GET_MODE (operands[2]) == DFmode
- && TARGET_SSE_PARTIAL_REGS && !optimize_size)
- {
- rtx op = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0);
- emit_insn (gen_sse2_unpcklpd (op, op, op));
- op = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0);
- emit_insn (gen_sse2_unpcklpd (op, op, op));
- }
-
- /* If op2 == op3, op3 would be clobbered before it is used. */
- if (operands_match_p (operands[2], operands[3]))
- {
- emit_move_insn (operands[0], operands[2]);
- DONE;
- }
-
- PUT_MODE (operands[1], GET_MODE (operands[0]));
- if (operands_match_p (operands[0], operands[4]))
- operands[6] = operands[4], operands[7] = operands[2];
- else
- operands[6] = operands[2], operands[7] = operands[4];
- operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
- operands[2] = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0);
- operands[3] = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0);
- operands[8] = simplify_gen_subreg (V2DFmode, operands[4], DFmode, 0);
- operands[6] = simplify_gen_subreg (V2DFmode, operands[6], DFmode, 0);
- operands[7] = simplify_gen_subreg (V2DFmode, operands[7], DFmode, 0);
-})
-
-;; Special case of conditional move we can handle effectively.
-;; Do not brother with the integer/floating point case, since these are
-;; bot considerably slower, unlike in the generic case.
-(define_insn "*sse_movsfcc_const0_1"
- [(set (match_operand:SF 0 "register_operand" "=&x")
- (if_then_else:SF (match_operator 1 "sse_comparison_operator"
- [(match_operand:SF 4 "register_operand" "0")
- (match_operand:SF 5 "nonimmediate_operand" "xm")])
- (match_operand:SF 2 "register_operand" "x")
- (match_operand:SF 3 "const0_operand" "X")))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*sse_movsfcc_const0_2"
- [(set (match_operand:SF 0 "register_operand" "=&x")
- (if_then_else:SF (match_operator 1 "sse_comparison_operator"
- [(match_operand:SF 4 "register_operand" "0")
- (match_operand:SF 5 "nonimmediate_operand" "xm")])
- (match_operand:SF 2 "const0_operand" "X")
- (match_operand:SF 3 "register_operand" "x")))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*sse_movsfcc_const0_3"
- [(set (match_operand:SF 0 "register_operand" "=&x")
- (if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
- [(match_operand:SF 4 "nonimmediate_operand" "xm")
- (match_operand:SF 5 "register_operand" "0")])
- (match_operand:SF 2 "register_operand" "x")
- (match_operand:SF 3 "const0_operand" "X")))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*sse_movsfcc_const0_4"
- [(set (match_operand:SF 0 "register_operand" "=&x")
- (if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
- [(match_operand:SF 4 "nonimmediate_operand" "xm")
- (match_operand:SF 5 "register_operand" "0")])
- (match_operand:SF 2 "const0_operand" "X")
- (match_operand:SF 3 "register_operand" "x")))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*sse_movdfcc_const0_1"
- [(set (match_operand:DF 0 "register_operand" "=&Y")
- (if_then_else:DF (match_operator 1 "sse_comparison_operator"
- [(match_operand:DF 4 "register_operand" "0")
- (match_operand:DF 5 "nonimmediate_operand" "Ym")])
- (match_operand:DF 2 "register_operand" "Y")
- (match_operand:DF 3 "const0_operand" "X")))]
- "TARGET_SSE2"
- "#")
-
-(define_insn "*sse_movdfcc_const0_2"
- [(set (match_operand:DF 0 "register_operand" "=&Y")
- (if_then_else:DF (match_operator 1 "sse_comparison_operator"
- [(match_operand:DF 4 "register_operand" "0")
- (match_operand:DF 5 "nonimmediate_operand" "Ym")])
- (match_operand:DF 2 "const0_operand" "X")
- (match_operand:DF 3 "register_operand" "Y")))]
- "TARGET_SSE2"
- "#")
-
-(define_insn "*sse_movdfcc_const0_3"
- [(set (match_operand:DF 0 "register_operand" "=&Y")
- (if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
- [(match_operand:DF 4 "nonimmediate_operand" "Ym")
- (match_operand:DF 5 "register_operand" "0")])
- (match_operand:DF 2 "register_operand" "Y")
- (match_operand:DF 3 "const0_operand" "X")))]
- "TARGET_SSE2"
- "#")
-
-(define_insn "*sse_movdfcc_const0_4"
- [(set (match_operand:DF 0 "register_operand" "=&Y")
- (if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
- [(match_operand:DF 4 "nonimmediate_operand" "Ym")
- (match_operand:DF 5 "register_operand" "0")])
- (match_operand:DF 2 "const0_operand" "X")
- (match_operand:DF 3 "register_operand" "Y")))]
- "TARGET_SSE2"
- "#")
-
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (match_operator 1 "comparison_operator"
- [(match_operand:SF 4 "nonimmediate_operand" "")
- (match_operand:SF 5 "nonimmediate_operand" "")])
- (match_operand:SF 2 "nonmemory_operand" "")
- (match_operand:SF 3 "nonmemory_operand" "")))]
- "SSE_REG_P (operands[0]) && reload_completed
- && (const0_operand (operands[2], GET_MODE (operands[0]))
- || const0_operand (operands[3], GET_MODE (operands[0])))"
- [(set (match_dup 0) (match_op_dup 1 [(match_dup 0) (match_dup 5)]))
- (set (match_dup 8) (and:V4SF (match_dup 6) (match_dup 7)))]
-{
- PUT_MODE (operands[1], GET_MODE (operands[0]));
- if (!sse_comparison_operator (operands[1], VOIDmode)
- || !rtx_equal_p (operands[0], operands[4]))
- {
- rtx tmp = operands[5];
- operands[5] = operands[4];
- operands[4] = tmp;
- PUT_CODE (operands[1], swap_condition (GET_CODE (operands[1])));
- }
- if (!rtx_equal_p (operands[0], operands[4]))
- abort ();
- operands[8] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
- if (const0_operand (operands[2], GET_MODE (operands[2])))
- {
- operands[7] = operands[3];
- operands[6] = gen_rtx_NOT (V4SFmode, operands[5]);
- }
- else
- {
- operands[7] = operands[2];
- operands[6] = operands[8];
- }
- operands[7] = simplify_gen_subreg (V4SFmode, operands[7], SFmode, 0);
-})
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (if_then_else:DF (match_operator 1 "comparison_operator"
- [(match_operand:DF 4 "nonimmediate_operand" "")
- (match_operand:DF 5 "nonimmediate_operand" "")])
- (match_operand:DF 2 "nonmemory_operand" "")
- (match_operand:DF 3 "nonmemory_operand" "")))]
- "SSE_REG_P (operands[0]) && reload_completed
- && (const0_operand (operands[2], GET_MODE (operands[0]))
- || const0_operand (operands[3], GET_MODE (operands[0])))"
- [(set (match_dup 0) (match_op_dup 1 [(match_dup 0) (match_dup 5)]))
- (set (match_dup 8) (and:V2DF (match_dup 6) (match_dup 7)))]
-{
- if (TARGET_SSE_PARTIAL_REGS && !optimize_size
- && GET_MODE (operands[2]) == DFmode)
- {
- if (REG_P (operands[2]))
- {
- rtx op = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0);
- emit_insn (gen_sse2_unpcklpd (op, op, op));
- }
- if (REG_P (operands[3]))
- {
- rtx op = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0);
- emit_insn (gen_sse2_unpcklpd (op, op, op));
- }
- }
- PUT_MODE (operands[1], GET_MODE (operands[0]));
- if (!sse_comparison_operator (operands[1], VOIDmode)
- || !rtx_equal_p (operands[0], operands[4]))
- {
- rtx tmp = operands[5];
- operands[5] = operands[4];
- operands[4] = tmp;
- PUT_CODE (operands[1], swap_condition (GET_CODE (operands[1])));
- }
- if (!rtx_equal_p (operands[0], operands[4]))
- abort ();
- operands[8] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
- if (const0_operand (operands[2], GET_MODE (operands[2])))
- {
- operands[7] = operands[3];
- operands[6] = gen_rtx_NOT (V2DFmode, operands[8]);
- }
- else
- {
- operands[7] = operands[2];
- operands[6] = operands[8];
- }
- operands[7] = simplify_gen_subreg (V2DFmode, operands[7], DFmode, 0);
-})
-
(define_expand "allocate_stack_worker"
[(match_operand:SI 0 "register_operand" "")]
"TARGET_STACK_PROBE"
@@ -17353,9 +19402,9 @@
(define_insn "allocate_stack_worker_1"
[(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
UNSPECV_STACK_PROBE)
- (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0)))
+ (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
(clobber (match_scratch:SI 1 "=0"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_STACK_PROBE"
"call\t__alloca"
[(set_attr "type" "multi")
@@ -17364,18 +19413,18 @@
(define_expand "allocate_stack_worker_postreload"
[(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
UNSPECV_STACK_PROBE)
- (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0)))
+ (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
(clobber (match_dup 0))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
(define_insn "allocate_stack_worker_rex64"
[(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
UNSPECV_STACK_PROBE)
- (set (reg:DI 7) (minus:DI (reg:DI 7) (match_dup 0)))
+ (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
(clobber (match_scratch:DI 1 "=0"))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && TARGET_STACK_PROBE"
"call\t__alloca"
[(set_attr "type" "multi")
@@ -17384,20 +19433,20 @@
(define_expand "allocate_stack_worker_rex64_postreload"
[(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
UNSPECV_STACK_PROBE)
- (set (reg:DI 7) (minus:DI (reg:DI 7) (match_dup 0)))
+ (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
(clobber (match_dup 0))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
""
"")
(define_expand "allocate_stack"
[(parallel [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (reg:SI 7)
+ (minus:SI (reg:SI SP_REG)
(match_operand:SI 1 "general_operand" "")))
- (clobber (reg:CC 17))])
- (parallel [(set (reg:SI 7)
- (minus:SI (reg:SI 7) (match_dup 1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel [(set (reg:SI SP_REG)
+ (minus:SI (reg:SI SP_REG) (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))])]
"TARGET_STACK_PROBE"
{
#ifdef CHECK_STACK_LIMIT
@@ -17418,7 +19467,21 @@
[(label_ref (match_operand 0 "" ""))]
"!TARGET_64BIT && flag_pic"
{
- emit_insn (gen_set_got (pic_offset_table_rtx));
+ if (TARGET_MACHO)
+ {
+ rtx xops[3];
+ rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
+ rtx label_rtx = gen_label_rtx ();
+ emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx));
+ xops[0] = xops[1] = picreg;
+ xops[2] = gen_rtx_CONST (SImode,
+ gen_rtx_MINUS (SImode,
+ gen_rtx_LABEL_REF (SImode, label_rtx),
+ gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME)));
+ ix86_expand_binary_operator (MINUS, SImode, xops);
+ }
+ else
+ emit_insn (gen_set_got (pic_offset_table_rtx));
DONE;
})
@@ -17429,17 +19492,18 @@
(match_operator 3 "promotable_binary_operator"
[(match_operand 1 "register_operand" "")
(match_operand 2 "aligned_operand" "")]))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"! TARGET_PARTIAL_REG_STALL && reload_completed
&& ((GET_MODE (operands[0]) == HImode
&& ((!optimize_size && !TARGET_FAST_PREFIX)
+ /* ??? next two lines just !satisfies_constraint_K (...) */
|| GET_CODE (operands[2]) != CONST_INT
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')))
+ || satisfies_constraint_K (operands[2])))
|| (GET_MODE (operands[0]) == QImode
&& (TARGET_PROMOTE_QImode || optimize_size)))"
[(parallel [(set (match_dup 0)
(match_op_dup 3 [(match_dup 1) (match_dup 2)]))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);
if (GET_CODE (operands[3]) != ASHIFT)
@@ -17505,14 +19569,14 @@
(define_split
[(set (match_operand 0 "register_operand" "")
(neg (match_operand 1 "register_operand" "")))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC FLAGS_REG))]
"! TARGET_PARTIAL_REG_STALL && reload_completed
&& (GET_MODE (operands[0]) == HImode
|| (GET_MODE (operands[0]) == QImode
&& (TARGET_PROMOTE_QImode || optimize_size)))"
[(parallel [(set (match_dup 0)
(neg:SI (match_dup 1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);")
@@ -17531,7 +19595,7 @@
(define_split
[(set (match_operand 0 "register_operand" "")
(if_then_else (match_operator 1 "comparison_operator"
- [(reg 17) (const_int 0)])
+ [(reg FLAGS_REG) (const_int 0)])
(match_operand 2 "register_operand" "")
(match_operand 3 "register_operand" "")))]
"! TARGET_PARTIAL_REG_STALL && TARGET_CMOVE
@@ -17553,7 +19617,8 @@
[(set (match_operand:SI 0 "push_operand" "")
(match_operand:SI 1 "memory_operand" ""))
(match_scratch:SI 2 "r")]
- "! optimize_size && ! TARGET_PUSH_MEMORY"
+ "!optimize_size && !TARGET_PUSH_MEMORY
+ && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (match_dup 2))]
"")
@@ -17562,7 +19627,8 @@
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "memory_operand" ""))
(match_scratch:DI 2 "r")]
- "! optimize_size && ! TARGET_PUSH_MEMORY"
+ "!optimize_size && !TARGET_PUSH_MEMORY
+ && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (match_dup 2))]
"")
@@ -17573,7 +19639,8 @@
[(set (match_operand:SF 0 "push_operand" "")
(match_operand:SF 1 "memory_operand" ""))
(match_scratch:SF 2 "r")]
- "! optimize_size && ! TARGET_PUSH_MEMORY"
+ "!optimize_size && !TARGET_PUSH_MEMORY
+ && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (match_dup 2))]
"")
@@ -17582,7 +19649,8 @@
[(set (match_operand:HI 0 "push_operand" "")
(match_operand:HI 1 "memory_operand" ""))
(match_scratch:HI 2 "r")]
- "! optimize_size && ! TARGET_PUSH_MEMORY"
+ "!optimize_size && !TARGET_PUSH_MEMORY
+ && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (match_dup 2))]
"")
@@ -17591,7 +19659,8 @@
[(set (match_operand:QI 0 "push_operand" "")
(match_operand:QI 1 "memory_operand" ""))
(match_scratch:QI 2 "q")]
- "! optimize_size && ! TARGET_PUSH_MEMORY"
+ "!optimize_size && !TARGET_PUSH_MEMORY
+ && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (match_dup 2))]
"")
@@ -17608,7 +19677,7 @@
&& get_attr_length (insn) >= ix86_cost->large_insn
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 1) (const_int 0))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(set (match_dup 0) (match_dup 1))]
"")
@@ -17622,7 +19691,7 @@
&& get_attr_length (insn) >= ix86_cost->large_insn
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 2) (const_int 0))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(set (match_dup 0) (match_dup 1))]
"operands[2] = gen_lowpart (SImode, operands[1]);")
@@ -17636,7 +19705,7 @@
&& get_attr_length (insn) >= ix86_cost->large_insn
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 2) (const_int 0))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(set (match_dup 0) (match_dup 1))]
"operands[2] = gen_lowpart (SImode, operands[1]);")
@@ -17687,7 +19756,7 @@
;; Don't split NOTs with a displacement operand, because resulting XOR
;; will not be pairable anyway.
;;
-;; On AMD K6, NOT is vector decoded with memory operand that can not be
+;; On AMD K6, NOT is vector decoded with memory operand that cannot be
;; represented using a modRM byte. The XOR replacement is long decoded,
;; so this split helps here as well.
;;
@@ -17705,7 +19774,7 @@
|| (TARGET_K6 && long_memory_operand (operands[0], SImode)))"
[(parallel [(set (match_dup 0)
(xor:SI (match_dup 1) (const_int -1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_peephole2
@@ -17719,7 +19788,7 @@
|| (TARGET_K6 && long_memory_operand (operands[0], HImode)))"
[(parallel [(set (match_dup 0)
(xor:HI (match_dup 1) (const_int -1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_peephole2
@@ -17733,7 +19802,7 @@
|| (TARGET_K6 && long_memory_operand (operands[0], QImode)))"
[(parallel [(set (match_dup 0)
(xor:QI (match_dup 1) (const_int -1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
;; Non pairable "test imm, reg" instructions can be translated to
@@ -17751,8 +19820,7 @@
(const_int 0)]))]
"ix86_match_ccmode (insn, CCNOmode)
&& (true_regnum (operands[2]) != 0
- || (GET_CODE (operands[3]) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'K')))
+ || satisfies_constraint_K (operands[3]))
&& peep2_reg_dead_p (1, operands[2])"
[(parallel
[(set (match_dup 0)
@@ -17824,12 +19892,12 @@
(match_operator:SI 3 "arith_or_logical_operator"
[(match_dup 0)
(match_operand:SI 1 "memory_operand" "")]))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"! optimize_size && ! TARGET_READ_MODIFY"
[(set (match_dup 2) (match_dup 1))
(parallel [(set (match_dup 0)
(match_op_dup 3 [(match_dup 0) (match_dup 2)]))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_peephole2
@@ -17838,12 +19906,12 @@
(match_operator:SI 3 "arith_or_logical_operator"
[(match_operand:SI 1 "memory_operand" "")
(match_dup 0)]))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"! optimize_size && ! TARGET_READ_MODIFY"
[(set (match_dup 2) (match_dup 1))
(parallel [(set (match_dup 0)
(match_op_dup 3 [(match_dup 2) (match_dup 0)]))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
; Don't do logical operations with memory outputs
@@ -17858,12 +19926,12 @@
(match_operator:SI 3 "arith_or_logical_operator"
[(match_dup 0)
(match_operand:SI 1 "nonmemory_operand" "")]))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"! optimize_size && ! TARGET_READ_MODIFY_WRITE"
[(set (match_dup 2) (match_dup 0))
(parallel [(set (match_dup 2)
(match_op_dup 3 [(match_dup 2) (match_dup 1)]))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(set (match_dup 0) (match_dup 2))]
"")
@@ -17873,29 +19941,28 @@
(match_operator:SI 3 "arith_or_logical_operator"
[(match_operand:SI 1 "nonmemory_operand" "")
(match_dup 0)]))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"! optimize_size && ! TARGET_READ_MODIFY_WRITE"
[(set (match_dup 2) (match_dup 0))
(parallel [(set (match_dup 2)
(match_op_dup 3 [(match_dup 1) (match_dup 2)]))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(set (match_dup 0) (match_dup 2))]
"")
;; Attempt to always use XOR for zeroing registers.
(define_peephole2
[(set (match_operand 0 "register_operand" "")
- (const_int 0))]
- "(GET_MODE (operands[0]) == QImode
- || GET_MODE (operands[0]) == HImode
- || GET_MODE (operands[0]) == SImode
- || (GET_MODE (operands[0]) == DImode && TARGET_64BIT))
+ (match_operand 1 "const0_operand" ""))]
+ "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& (! TARGET_USE_MOV0 || optimize_size)
+ && GENERAL_REG_P (operands[0])
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (const_int 0))
- (clobber (reg:CC 17))])]
- "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode,
- operands[0]);")
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ operands[0] = gen_lowpart (word_mode, operands[0]);
+})
(define_peephole2
[(set (strict_low_part (match_operand 0 "register_operand" ""))
@@ -17905,7 +19972,7 @@
&& (! TARGET_USE_MOV0 || optimize_size)
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (strict_low_part (match_dup 0)) (const_int 0))
- (clobber (reg:CC 17))])])
+ (clobber (reg:CC FLAGS_REG))])])
;; For HI and SI modes, or $-1,reg is smaller than mov $-1,reg.
(define_peephole2
@@ -17917,7 +19984,7 @@
&& (optimize_size || TARGET_PENTIUM)
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (const_int -1))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode,
operands[0]);")
@@ -17929,7 +19996,7 @@
(match_operand:SI 1 "nonmemory_operand" "")))]
"peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_peephole2
@@ -17938,7 +20005,7 @@
(match_operand:DI 2 "nonmemory_operand" "")) 0))]
"peep2_regno_dead_p (0, FLAGS_REG) && REGNO (operands[0]) == REGNO (operands[1])"
[(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[2] = gen_lowpart (SImode, operands[2]);")
(define_peephole2
@@ -17947,7 +20014,7 @@
(match_operand:DI 1 "x86_64_general_operand" "")))]
"peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_peephole2
@@ -17957,7 +20024,7 @@
"exact_log2 (INTVAL (operands[1])) >= 0
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
(define_peephole2
@@ -17967,7 +20034,7 @@
"exact_log2 (INTVAL (operands[1])) >= 0
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
(define_peephole2
@@ -17978,7 +20045,7 @@
&& REGNO (operands[0]) == REGNO (operands[1])
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));")
;; The ESP adjustments can be done by the push and pop instructions. Resulting
@@ -18002,52 +20069,52 @@
(define_peephole2
[(match_scratch:SI 0 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_SUB_ESP_4"
[(clobber (match_dup 0))
- (parallel [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
+ (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
(clobber (mem:BLK (scratch)))])])
(define_peephole2
[(match_scratch:SI 0 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_SUB_ESP_8"
[(clobber (match_dup 0))
- (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
- (parallel [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
+ (parallel [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
(clobber (mem:BLK (scratch)))])])
;; Convert esp subtractions to push.
(define_peephole2
[(match_scratch:SI 0 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (clobber (reg:CC FLAGS_REG))])]
"optimize_size || !TARGET_SUB_ESP_4"
[(clobber (match_dup 0))
- (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))])
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
(define_peephole2
[(match_scratch:SI 0 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (clobber (reg:CC FLAGS_REG))])]
"optimize_size || !TARGET_SUB_ESP_8"
[(clobber (match_dup 0))
- (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
- (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))])
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))])
;; Convert epilogue deallocator to pop.
(define_peephole2
[(match_scratch:SI 0 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_ADD_ESP_4"
- [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
+ [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
(clobber (mem:BLK (scratch)))])]
"")
@@ -18056,38 +20123,38 @@
(define_peephole2
[(match_scratch:SI 0 "r")
(match_scratch:SI 1 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_ADD_ESP_8"
- [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
+ [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
(clobber (mem:BLK (scratch)))])
- (parallel [(set (match_dup 1) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
+ (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
"")
(define_peephole2
[(match_scratch:SI 0 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size"
- [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
+ [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
(clobber (mem:BLK (scratch)))])
- (parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
+ (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
"")
;; Convert esp additions to pop.
(define_peephole2
[(match_scratch:SI 0 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
+ (clobber (reg:CC FLAGS_REG))])]
""
- [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
+ [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
"")
;; Two pops case is tricky, since pop causes dependency on destination register.
@@ -18095,24 +20162,24 @@
(define_peephole2
[(match_scratch:SI 0 "r")
(match_scratch:SI 1 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
+ (clobber (reg:CC FLAGS_REG))])]
""
- [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])
- (parallel [(set (match_dup 1) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
+ [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
+ (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
"")
(define_peephole2
[(match_scratch:SI 0 "r")
- (parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
+ (clobber (reg:CC FLAGS_REG))])]
"optimize_size"
- [(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])
- (parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
- (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
+ [(parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])
+ (parallel [(set (match_dup 0) (mem:SI (reg:SI SP_REG)))
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
"")
;; Convert compares with 1 to shorter inc/dec operations when CF is not
@@ -18134,52 +20201,52 @@
(define_peephole2
[(match_scratch:DI 0 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_SUB_ESP_4"
[(clobber (match_dup 0))
- (parallel [(set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0))
+ (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
(clobber (mem:BLK (scratch)))])])
(define_peephole2
[(match_scratch:DI 0 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_SUB_ESP_8"
[(clobber (match_dup 0))
- (set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0))
- (parallel [(set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0))
+ (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
+ (parallel [(set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
(clobber (mem:BLK (scratch)))])])
;; Convert esp subtractions to push.
(define_peephole2
[(match_scratch:DI 0 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -8)))
+ (clobber (reg:CC FLAGS_REG))])]
"optimize_size || !TARGET_SUB_ESP_4"
[(clobber (match_dup 0))
- (set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0))])
+ (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
(define_peephole2
[(match_scratch:DI 0 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int -16)))
+ (clobber (reg:CC FLAGS_REG))])]
"optimize_size || !TARGET_SUB_ESP_8"
[(clobber (match_dup 0))
- (set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0))
- (set (mem:DI (pre_dec:DI (reg:DI 7))) (match_dup 0))])
+ (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))
+ (set (mem:DI (pre_dec:DI (reg:DI SP_REG))) (match_dup 0))])
;; Convert epilogue deallocator to pop.
(define_peephole2
[(match_scratch:DI 0 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_ADD_ESP_4"
- [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))
+ [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
(clobber (mem:BLK (scratch)))])]
"")
@@ -18188,38 +20255,38 @@
(define_peephole2
[(match_scratch:DI 0 "r")
(match_scratch:DI 1 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 16)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_ADD_ESP_8"
- [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))
+ [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
(clobber (mem:BLK (scratch)))])
- (parallel [(set (match_dup 1) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])]
+ (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
"")
(define_peephole2
[(match_scratch:DI 0 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 16)))
- (clobber (reg:CC 17))
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
+ (clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"optimize_size"
- [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))
+ [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
(clobber (mem:BLK (scratch)))])
- (parallel [(set (match_dup 0) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])]
+ (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
"")
;; Convert esp additions to pop.
(define_peephole2
[(match_scratch:DI 0 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))
+ (clobber (reg:CC FLAGS_REG))])]
""
- [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])]
+ [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
"")
;; Two pops case is tricky, since pop causes dependency on destination register.
@@ -18227,26 +20294,89 @@
(define_peephole2
[(match_scratch:DI 0 "r")
(match_scratch:DI 1 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 16)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
+ (clobber (reg:CC FLAGS_REG))])]
""
- [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])
- (parallel [(set (match_dup 1) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])]
+ [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
+ (parallel [(set (match_dup 1) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
"")
(define_peephole2
[(match_scratch:DI 0 "r")
- (parallel [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 16)))
- (clobber (reg:CC 17))])]
+ (parallel [(set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 16)))
+ (clobber (reg:CC FLAGS_REG))])]
"optimize_size"
- [(parallel [(set (match_dup 0) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])
- (parallel [(set (match_dup 0) (mem:DI (reg:DI 7)))
- (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])]
+ [(parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])
+ (parallel [(set (match_dup 0) (mem:DI (reg:DI SP_REG)))
+ (set (reg:DI SP_REG) (plus:DI (reg:DI SP_REG) (const_int 8)))])]
"")
+;; Convert imul by three, five and nine into lea
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "INTVAL (operands[2]) == 3
+ || INTVAL (operands[2]) == 5
+ || INTVAL (operands[2]) == 9"
+ [(set (match_dup 0)
+ (plus:SI (mult:SI (match_dup 1) (match_dup 2))
+ (match_dup 1)))]
+ { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "!optimize_size
+ && (INTVAL (operands[2]) == 3
+ || INTVAL (operands[2]) == 5
+ || INTVAL (operands[2]) == 9)"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 0)
+ (plus:SI (mult:SI (match_dup 0) (match_dup 2))
+ (match_dup 0)))]
+ { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mult:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "const_int_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT
+ && (INTVAL (operands[2]) == 3
+ || INTVAL (operands[2]) == 5
+ || INTVAL (operands[2]) == 9)"
+ [(set (match_dup 0)
+ (plus:DI (mult:DI (match_dup 1) (match_dup 2))
+ (match_dup 1)))]
+ { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
+ (match_operand:DI 2 "const_int_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_64BIT
+ && !optimize_size
+ && (INTVAL (operands[2]) == 3
+ || INTVAL (operands[2]) == 5
+ || INTVAL (operands[2]) == 9)"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 0)
+ (plus:DI (mult:DI (match_dup 0) (match_dup 2))
+ (match_dup 0)))]
+ { operands[2] = GEN_INT (INTVAL (operands[2]) - 1); })
+
;; Imul $32bit_imm, mem, reg is vector decoded, while
;; imul $32bit_imm, reg, reg is direct decoded.
(define_peephole2
@@ -18254,13 +20384,12 @@
(parallel [(set (match_operand:DI 0 "register_operand" "")
(mult:DI (match_operand:DI 1 "memory_operand" "")
(match_operand:DI 2 "immediate_operand" "")))
- (clobber (reg:CC 17))])]
- "TARGET_K8 && !optimize_size
- && (GET_CODE (operands[2]) != CONST_INT
- || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+ (clobber (reg:CC FLAGS_REG))])]
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && !satisfies_constraint_K (operands[2])"
[(set (match_dup 3) (match_dup 1))
(parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_peephole2
@@ -18268,13 +20397,12 @@
(parallel [(set (match_operand:SI 0 "register_operand" "")
(mult:SI (match_operand:SI 1 "memory_operand" "")
(match_operand:SI 2 "immediate_operand" "")))
- (clobber (reg:CC 17))])]
- "TARGET_K8 && !optimize_size
- && (GET_CODE (operands[2]) != CONST_INT
- || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+ (clobber (reg:CC FLAGS_REG))])]
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && !satisfies_constraint_K (operands[2])"
[(set (match_dup 3) (match_dup 1))
(parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
(define_peephole2
@@ -18283,13 +20411,12 @@
(zero_extend:DI
(mult:SI (match_operand:SI 1 "memory_operand" "")
(match_operand:SI 2 "immediate_operand" ""))))
- (clobber (reg:CC 17))])]
- "TARGET_K8 && !optimize_size
- && (GET_CODE (operands[2]) != CONST_INT
- || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+ (clobber (reg:CC FLAGS_REG))])]
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && !satisfies_constraint_K (operands[2])"
[(set (match_dup 3) (match_dup 1))
(parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2))))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
"")
;; imul $8/16bit_imm, regmem, reg is vector decoded.
@@ -18300,13 +20427,13 @@
[(parallel [(set (match_operand:DI 0 "register_operand" "")
(mult:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "const_int_operand" "")))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(match_scratch:DI 3 "r")]
- "TARGET_K8 && !optimize_size
- && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && satisfies_constraint_K (operands[2])"
[(set (match_dup 3) (match_dup 2))
(parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
{
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
@@ -18316,13 +20443,13 @@
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(mult:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(match_scratch:SI 3 "r")]
- "TARGET_K8 && !optimize_size
- && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
+ && satisfies_constraint_K (operands[2])"
[(set (match_dup 3) (match_dup 2))
(parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
{
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
@@ -18332,16 +20459,74 @@
[(parallel [(set (match_operand:HI 0 "register_operand" "")
(mult:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "immediate_operand" "")))
- (clobber (reg:CC 17))])
+ (clobber (reg:CC FLAGS_REG))])
(match_scratch:HI 3 "r")]
- "TARGET_K8 && !optimize_size"
+ "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size"
[(set (match_dup 3) (match_dup 2))
(parallel [(set (match_dup 0) (mult:HI (match_dup 0) (match_dup 3)))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC FLAGS_REG))])]
{
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
})
+
+;; After splitting up read-modify operations, array accesses with memory
+;; operands might end up in form:
+;; sall $2, %eax
+;; movl 4(%esp), %edx
+;; addl %edx, %eax
+;; instead of pre-splitting:
+;; sall $2, %eax
+;; addl 4(%esp), %eax
+;; Turn it into:
+;; movl 4(%esp), %edx
+;; leal (%edx,%eax,4), %eax
+
+(define_peephole2
+ [(parallel [(set (match_operand 0 "register_operand" "")
+ (ashift (match_operand 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (match_operand 3 "register_operand")
+ (match_operand 4 "x86_64_general_operand" ""))
+ (parallel [(set (match_operand 5 "register_operand" "")
+ (plus (match_operand 6 "register_operand" "")
+ (match_operand 7 "register_operand" "")))
+ (clobber (reg:CC FLAGS_REG))])]
+ "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
+ /* Validate MODE for lea. */
+ && ((!TARGET_PARTIAL_REG_STALL
+ && (GET_MODE (operands[0]) == QImode
+ || GET_MODE (operands[0]) == HImode))
+ || GET_MODE (operands[0]) == SImode
+ || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
+ /* We reorder load and the shift. */
+ && !rtx_equal_p (operands[1], operands[3])
+ && !reg_overlap_mentioned_p (operands[0], operands[4])
+ /* Last PLUS must consist of operand 0 and 3. */
+ && !rtx_equal_p (operands[0], operands[3])
+ && (rtx_equal_p (operands[3], operands[6])
+ || rtx_equal_p (operands[3], operands[7]))
+ && (rtx_equal_p (operands[0], operands[6])
+ || rtx_equal_p (operands[0], operands[7]))
+ /* The intermediate operand 0 must die or be same as output. */
+ && (rtx_equal_p (operands[0], operands[5])
+ || peep2_reg_dead_p (3, operands[0]))"
+ [(set (match_dup 3) (match_dup 4))
+ (set (match_dup 0) (match_dup 1))]
+{
+ enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
+ int scale = 1 << INTVAL (operands[2]);
+ rtx index = gen_lowpart (Pmode, operands[1]);
+ rtx base = gen_lowpart (Pmode, operands[3]);
+ rtx dest = gen_lowpart (mode, operands[5]);
+
+ operands[1] = gen_rtx_PLUS (Pmode, base,
+ gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
+ if (mode != Pmode)
+ operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
+ operands[0] = dest;
+})
;; Call-value patterns last so that the wildcard operand does not
;; disrupt insn-recog's switch tables.
@@ -18350,7 +20535,7 @@
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
(match_operand:SI 2 "" "")))
- (set (reg:SI 7) (plus:SI (reg:SI 7)
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
(match_operand:SI 3 "immediate_operand" "")))]
"!TARGET_64BIT"
{
@@ -18365,11 +20550,11 @@
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
(match_operand:SI 2 "" "")))
- (set (reg:SI 7) (plus:SI (reg:SI 7)
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
(match_operand:SI 3 "immediate_operand" "i")))]
"!TARGET_64BIT"
{
- if (constant_call_address_operand (operands[1], QImode))
+ if (constant_call_address_operand (operands[1], Pmode))
{
if (SIBLING_CALL_P (insn))
return "jmp\t%P1";
@@ -18415,7 +20600,7 @@
(match_operand:SI 2 "" "")))]
"!SIBLING_CALL_P (insn) && !TARGET_64BIT"
{
- if (constant_call_address_operand (operands[1], QImode))
+ if (constant_call_address_operand (operands[1], Pmode))
return "call\t%P1";
return "call\t%A1";
}
@@ -18427,7 +20612,7 @@
(match_operand:SI 2 "" "")))]
"SIBLING_CALL_P (insn) && !TARGET_64BIT"
{
- if (constant_call_address_operand (operands[1], QImode))
+ if (constant_call_address_operand (operands[1], Pmode))
return "jmp\t%P1";
return "jmp\t%A1";
}
@@ -18439,7 +20624,7 @@
(match_operand:DI 2 "" "")))]
"!SIBLING_CALL_P (insn) && TARGET_64BIT"
{
- if (constant_call_address_operand (operands[1], QImode))
+ if (constant_call_address_operand (operands[1], Pmode))
return "call\t%P1";
return "call\t%A1";
}
@@ -18461,2402 +20646,16 @@
"jmp\t*%%r11"
[(set_attr "type" "callv")])
+;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5.
+;; That, however, is usually mapped by the OS to SIGSEGV, which is often
+;; caught for use by garbage collectors and the like. Using an insn that
+;; maps to SIGILL makes it more likely the program will rightfully die.
+;; Keeping with tradition, "6" is in honor of #UD.
(define_insn "trap"
- [(trap_if (const_int 1) (const_int 5))]
+ [(trap_if (const_int 1) (const_int 6))]
""
- "int\t$5")
-
-;;; ix86 doesn't have conditional trap instructions, but we fake them
-;;; for the sake of bounds checking. By emitting bounds checks as
-;;; conditional traps rather than as conditional jumps around
-;;; unconditional traps we avoid introducing spurious basic-block
-;;; boundaries and facilitate elimination of redundant checks. In
-;;; honor of the too-inflexible-for-BPs `bound' instruction, we use
-;;; interrupt 5.
-;;;
-;;; FIXME: Static branch prediction rules for ix86 are such that
-;;; forward conditional branches predict as untaken. As implemented
-;;; below, pseudo conditional traps violate that rule. We should use
-;;; .pushsection/.popsection to place all of the `int 5's in a special
-;;; section loaded at the end of the text segment and branch forward
-;;; there on bounds-failure, and then jump back immediately (in case
-;;; the system chooses to ignore bounds violations, or to report
-;;; violations and continue execution).
-
-(define_expand "conditional_trap"
- [(trap_if (match_operator 0 "comparison_operator"
- [(match_dup 2) (const_int 0)])
- (match_operand 1 "const_int_operand" ""))]
- ""
-{
- emit_insn (gen_rtx_TRAP_IF (VOIDmode,
- ix86_expand_compare (GET_CODE (operands[0]),
- NULL, NULL),
- operands[1]));
- DONE;
-})
-
-(define_insn "*conditional_trap_1"
- [(trap_if (match_operator 0 "comparison_operator"
- [(reg 17) (const_int 0)])
- (match_operand 1 "const_int_operand" ""))]
- ""
-{
- operands[2] = gen_label_rtx ();
- output_asm_insn ("j%c0\t%l2\; int\t%1", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[2]));
- RET;
-})
-
- ;; Pentium III SIMD instructions.
-
-;; Moves for SSE/MMX regs.
-
-(define_insn "*movv4sf_internal"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:V4SF 1 "vector_move_operand" "C,xm,x"))]
- "TARGET_SSE
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "@
- xorps\t%0, %0
- movaps\t{%1, %0|%0, %1}
- movaps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V4SF")])
-
-(define_split
- [(set (match_operand:V4SF 0 "register_operand" "")
- (match_operand:V4SF 1 "zero_extended_scalar_load_operand" ""))]
- "TARGET_SSE && reload_completed"
- [(set (match_dup 0)
- (vec_merge:V4SF
- (vec_duplicate:V4SF (match_dup 1))
- (match_dup 2)
- (const_int 1)))]
-{
- operands[1] = simplify_gen_subreg (SFmode, operands[1], V4SFmode, 0);
- operands[2] = CONST0_RTX (V4SFmode);
-})
-
-(define_insn "*movv4si_internal"
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:V4SI 1 "vector_move_operand" "C,xm,x"))]
- "TARGET_SSE
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
- case 1:
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movdqa\t{%1, %0|%0, %1}";
- default:
- abort ();
- }
-}
- [(set_attr "type" "ssemov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "0,1")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "2")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
- (const_int 0))
- (ne (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "TI")))])
-
-(define_insn "*movv2di_internal"
- [(set (match_operand:V2DI 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:V2DI 1 "vector_move_operand" "C,xm,x"))]
- "TARGET_SSE
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
- case 1:
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movdqa\t{%1, %0|%0, %1}";
- default:
- abort ();
- }
-}
- [(set_attr "type" "ssemov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "0,1")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "2")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
- (const_int 0))
- (ne (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "TI")))])
-
-(define_split
- [(set (match_operand:V2DF 0 "register_operand" "")
- (match_operand:V2DF 1 "zero_extended_scalar_load_operand" ""))]
- "TARGET_SSE2 && reload_completed"
- [(set (match_dup 0)
- (vec_merge:V2DF
- (vec_duplicate:V2DF (match_dup 1))
- (match_dup 2)
- (const_int 1)))]
-{
- operands[1] = simplify_gen_subreg (DFmode, operands[1], V2DFmode, 0);
- operands[2] = CONST0_RTX (V2DFmode);
-})
-
-(define_insn "*movv2si_internal"
- [(set (match_operand:V2SI 0 "nonimmediate_operand"
- "=y,y ,m,!y,!*Y,*x,?*x,?m")
- (match_operand:V2SI 1 "vector_move_operand"
- "C ,ym,y,*Y,y ,C ,*xm,*x"))]
- "TARGET_MMX
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "@
- pxor\t%0, %0
- movq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}
- movdq2q\t{%1, %0|%0, %1}
- movq2dq\t{%1, %0|%0, %1}
- pxor\t%0, %0
- movq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov")
- (set_attr "mode" "DI")])
-
-(define_insn "*movv4hi_internal"
- [(set (match_operand:V4HI 0 "nonimmediate_operand"
- "=y,y ,m,!y,!*Y,*x,?*x,?m")
- (match_operand:V4HI 1 "vector_move_operand"
- "C ,ym,y,*Y,y ,C ,*xm,*x"))]
- "TARGET_MMX
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "@
- pxor\t%0, %0
- movq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}
- movdq2q\t{%1, %0|%0, %1}
- movq2dq\t{%1, %0|%0, %1}
- pxor\t%0, %0
- movq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov")
- (set_attr "mode" "DI")])
-
-(define_insn "*movv8qi_internal"
- [(set (match_operand:V8QI 0 "nonimmediate_operand"
- "=y,y ,m,!y,!*Y,*x,?*x,?m")
- (match_operand:V8QI 1 "vector_move_operand"
- "C ,ym,y,*Y,y ,C ,*xm,*x"))]
- "TARGET_MMX
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "@
- pxor\t%0, %0
- movq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}
- movdq2q\t{%1, %0|%0, %1}
- movq2dq\t{%1, %0|%0, %1}
- pxor\t%0, %0
- movq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov")
- (set_attr "mode" "DI")])
-
-(define_insn "*movv2sf_internal"
- [(set (match_operand:V2SF 0 "nonimmediate_operand"
- "=y,y ,m,!y,!*Y,*x,?*x,?m")
- (match_operand:V2SF 1 "vector_move_operand"
- "C ,ym,y,*Y,y ,C ,*xm,*x"))]
- "TARGET_MMX
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "@
- pxor\t%0, %0
- movq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}
- movdq2q\t{%1, %0|%0, %1}
- movq2dq\t{%1, %0|%0, %1}
- xorps\t%0, %0
- movq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov")
- (set_attr "mode" "DI")])
-
-(define_expand "movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "nonimmediate_operand" ""))]
- "TARGET_SSE || TARGET_64BIT"
-{
- if (TARGET_64BIT)
- ix86_expand_move (TImode, operands);
- else
- ix86_expand_vector_move (TImode, operands);
- DONE;
-})
-
-(define_expand "movtf"
- [(set (match_operand:TF 0 "nonimmediate_operand" "")
- (match_operand:TF 1 "nonimmediate_operand" ""))]
- "TARGET_64BIT"
-{
- ix86_expand_move (TFmode, operands);
- DONE;
-})
-
-(define_insn "*movv2df_internal"
- [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:V2DF 1 "vector_move_operand" "C,xm,x"))]
- "TARGET_SSE
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "xorpd\t%0, %0";
- case 1:
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movapd\t{%1, %0|%0, %1}";
- default:
- abort ();
- }
-}
- [(set_attr "type" "ssemov")
- (set (attr "mode")
- (cond [(eq (symbol_ref "TARGET_SSE2") (const_int 0))
- (const_string "V4SF")
- (eq_attr "alternative" "0,1")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "V2DF"))
- (eq_attr "alternative" "2")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
- (const_int 0))
- (ne (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "V2DF"))]
- (const_string "V2DF")))])
-
-(define_insn "*movv8hi_internal"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:V8HI 1 "vector_move_operand" "C,xm,x"))]
- "TARGET_SSE
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
- case 1:
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movdqa\t{%1, %0|%0, %1}";
- default:
- abort ();
- }
-}
- [(set_attr "type" "ssemov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "0,1")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "2")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
- (const_int 0))
- (ne (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "TI")))])
-
-(define_insn "*movv16qi_internal"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:V16QI 1 "vector_move_operand" "C,xm,x"))]
- "TARGET_SSE
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
- case 1:
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movdqa\t{%1, %0|%0, %1}";
- default:
- abort ();
- }
-}
- [(set_attr "type" "ssemov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "0,1")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "2")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
- (const_int 0))
- (ne (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "TI")))])
-
-(define_expand "movv2df"
- [(set (match_operand:V2DF 0 "nonimmediate_operand" "")
- (match_operand:V2DF 1 "nonimmediate_operand" ""))]
- "TARGET_SSE"
-{
- ix86_expand_vector_move (V2DFmode, operands);
- DONE;
-})
-
-(define_expand "movv8hi"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
- (match_operand:V8HI 1 "nonimmediate_operand" ""))]
- "TARGET_SSE"
-{
- ix86_expand_vector_move (V8HImode, operands);
- DONE;
-})
-
-(define_expand "movv16qi"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
- (match_operand:V16QI 1 "nonimmediate_operand" ""))]
- "TARGET_SSE"
-{
- ix86_expand_vector_move (V16QImode, operands);
- DONE;
-})
-
-(define_expand "movv4sf"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
- (match_operand:V4SF 1 "nonimmediate_operand" ""))]
- "TARGET_SSE"
-{
- ix86_expand_vector_move (V4SFmode, operands);
- DONE;
-})
-
-(define_expand "movv4si"
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
- (match_operand:V4SI 1 "nonimmediate_operand" ""))]
- "TARGET_SSE"
-{
- ix86_expand_vector_move (V4SImode, operands);
- DONE;
-})
-
-(define_expand "movv2di"
- [(set (match_operand:V2DI 0 "nonimmediate_operand" "")
- (match_operand:V2DI 1 "nonimmediate_operand" ""))]
- "TARGET_SSE"
-{
- ix86_expand_vector_move (V2DImode, operands);
- DONE;
-})
-
-(define_expand "movv2si"
- [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
- (match_operand:V2SI 1 "nonimmediate_operand" ""))]
- "TARGET_MMX"
-{
- ix86_expand_vector_move (V2SImode, operands);
- DONE;
-})
-
-(define_expand "movv4hi"
- [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
- (match_operand:V4HI 1 "nonimmediate_operand" ""))]
- "TARGET_MMX"
-{
- ix86_expand_vector_move (V4HImode, operands);
- DONE;
-})
-
-(define_expand "movv8qi"
- [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
- (match_operand:V8QI 1 "nonimmediate_operand" ""))]
- "TARGET_MMX"
-{
- ix86_expand_vector_move (V8QImode, operands);
- DONE;
-})
-
-(define_expand "movv2sf"
- [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
- (match_operand:V2SF 1 "nonimmediate_operand" ""))]
- "TARGET_MMX"
-{
- ix86_expand_vector_move (V2SFmode, operands);
- DONE;
-})
-
-(define_insn "*pushti"
- [(set (match_operand:TI 0 "push_operand" "=<")
- (match_operand:TI 1 "register_operand" "x"))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*pushv2df"
- [(set (match_operand:V2DF 0 "push_operand" "=<")
- (match_operand:V2DF 1 "register_operand" "x"))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*pushv2di"
- [(set (match_operand:V2DI 0 "push_operand" "=<")
- (match_operand:V2DI 1 "register_operand" "x"))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*pushv8hi"
- [(set (match_operand:V8HI 0 "push_operand" "=<")
- (match_operand:V8HI 1 "register_operand" "x"))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*pushv16qi"
- [(set (match_operand:V16QI 0 "push_operand" "=<")
- (match_operand:V16QI 1 "register_operand" "x"))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*pushv4sf"
- [(set (match_operand:V4SF 0 "push_operand" "=<")
- (match_operand:V4SF 1 "register_operand" "x"))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*pushv4si"
- [(set (match_operand:V4SI 0 "push_operand" "=<")
- (match_operand:V4SI 1 "register_operand" "x"))]
- "TARGET_SSE"
- "#")
-
-(define_insn "*pushv2si"
- [(set (match_operand:V2SI 0 "push_operand" "=<")
- (match_operand:V2SI 1 "register_operand" "y"))]
- "TARGET_MMX"
- "#")
-
-(define_insn "*pushv4hi"
- [(set (match_operand:V4HI 0 "push_operand" "=<")
- (match_operand:V4HI 1 "register_operand" "y"))]
- "TARGET_MMX"
- "#")
-
-(define_insn "*pushv8qi"
- [(set (match_operand:V8QI 0 "push_operand" "=<")
- (match_operand:V8QI 1 "register_operand" "y"))]
- "TARGET_MMX"
- "#")
-
-(define_insn "*pushv2sf"
- [(set (match_operand:V2SF 0 "push_operand" "=<")
- (match_operand:V2SF 1 "register_operand" "y"))]
- "TARGET_MMX"
- "#")
-
-(define_split
- [(set (match_operand 0 "push_operand" "")
- (match_operand 1 "register_operand" ""))]
- "!TARGET_64BIT && reload_completed
- && (SSE_REG_P (operands[1]) || MMX_REG_P (operands[1]))"
- [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 3)))
- (set (match_dup 2) (match_dup 1))]
- "operands[2] = change_address (operands[0], GET_MODE (operands[0]),
- stack_pointer_rtx);
- operands[3] = GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));")
-
-(define_split
- [(set (match_operand 0 "push_operand" "")
- (match_operand 1 "register_operand" ""))]
- "TARGET_64BIT && reload_completed
- && (SSE_REG_P (operands[1]) || MMX_REG_P (operands[1]))"
- [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 3)))
- (set (match_dup 2) (match_dup 1))]
- "operands[2] = change_address (operands[0], GET_MODE (operands[0]),
- stack_pointer_rtx);
- operands[3] = GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));")
-
-
-(define_insn "*movti_internal"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
- "TARGET_SSE && !TARGET_64BIT
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
- case 1:
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movdqa\t{%1, %0|%0, %1}";
- default:
- abort ();
- }
-}
- [(set_attr "type" "ssemov,ssemov,ssemov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "0,1")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "2")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "TI")))])
-
-(define_insn "*movti_rex64"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm")
- (match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))]
- "TARGET_64BIT
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
- case 1:
- return "#";
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
- case 3:
- case 4:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movdqa\t{%1, %0|%0, %1}";
- default:
- abort ();
- }
-}
- [(set_attr "type" "*,*,ssemov,ssemov,ssemov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "2,3")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "4")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
- (const_int 0))
- (ne (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "DI")))])
-
-(define_insn "*movtf_rex64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm")
- (match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))]
- "TARGET_64BIT
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
-{
- switch (which_alternative)
- {
- case 0:
- case 1:
- return "#";
- case 2:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "xorps\t%0, %0";
- else
- return "pxor\t%0, %0";
- case 3:
- case 4:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "movaps\t{%1, %0|%0, %1}";
- else
- return "movdqa\t{%1, %0|%0, %1}";
- default:
- abort ();
- }
-}
- [(set_attr "type" "*,*,ssemov,ssemov,ssemov")
- (set (attr "mode")
- (cond [(eq_attr "alternative" "2,3")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "4")
- (if_then_else
- (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
- (const_int 0))
- (ne (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "DI")))])
-
-(define_split
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "general_operand" ""))]
- "reload_completed && !SSE_REG_P (operands[0])
- && !SSE_REG_P (operands[1])"
- [(const_int 0)]
- "ix86_split_long_move (operands); DONE;")
-
-(define_split
- [(set (match_operand:TF 0 "nonimmediate_operand" "")
- (match_operand:TF 1 "general_operand" ""))]
- "reload_completed && !SSE_REG_P (operands[0])
- && !SSE_REG_P (operands[1])"
- [(const_int 0)]
- "ix86_split_long_move (operands); DONE;")
-
-;; These two patterns are useful for specifying exactly whether to use
-;; movaps or movups
-(define_expand "sse_movaps"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "")]
- UNSPEC_MOVA))]
- "TARGET_SSE"
-{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- {
- rtx tmp = gen_reg_rtx (V4SFmode);
- emit_insn (gen_sse_movaps (tmp, operands[1]));
- emit_move_insn (operands[0], tmp);
- DONE;
- }
-})
-
-(define_insn "*sse_movaps_1"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
- (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")]
- UNSPEC_MOVA))]
- "TARGET_SSE
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "movaps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov,ssemov")
- (set_attr "mode" "V4SF")])
-
-(define_expand "sse_movups"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "")]
- UNSPEC_MOVU))]
- "TARGET_SSE"
-{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- {
- rtx tmp = gen_reg_rtx (V4SFmode);
- emit_insn (gen_sse_movups (tmp, operands[1]));
- emit_move_insn (operands[0], tmp);
- DONE;
- }
-})
-
-(define_insn "*sse_movups_1"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
- (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")]
- UNSPEC_MOVU))]
- "TARGET_SSE
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "movups\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt,ssecvt")
- (set_attr "mode" "V4SF")])
-
-;; SSE Strange Moves.
-
-(define_insn "sse_movmskps"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V4SF 1 "register_operand" "x")]
- UNSPEC_MOVMSK))]
- "TARGET_SSE"
- "movmskps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "mmx_pmovmskb"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V8QI 1 "register_operand" "y")]
- UNSPEC_MOVMSK))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pmovmskb\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-
-(define_insn "mmx_maskmovq"
- [(set (mem:V8QI (match_operand:SI 0 "register_operand" "D"))
- (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")]
- UNSPEC_MASKMOV))]
- "(TARGET_SSE || TARGET_3DNOW_A) && !TARGET_64BIT"
- ;; @@@ check ordering of operands in intel/nonintel syntax
- "maskmovq\t{%2, %1|%1, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_maskmovq_rex"
- [(set (mem:V8QI (match_operand:DI 0 "register_operand" "D"))
- (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")]
- UNSPEC_MASKMOV))]
- "(TARGET_SSE || TARGET_3DNOW_A) && TARGET_64BIT"
- ;; @@@ check ordering of operands in intel/nonintel syntax
- "maskmovq\t{%2, %1|%1, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "sse_movntv4sf"
- [(set (match_operand:V4SF 0 "memory_operand" "=m")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "x")]
- UNSPEC_MOVNT))]
- "TARGET_SSE"
- "movntps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse_movntdi"
- [(set (match_operand:DI 0 "memory_operand" "=m")
- (unspec:DI [(match_operand:DI 1 "register_operand" "y")]
- UNSPEC_MOVNT))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "movntq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxmov")
- (set_attr "mode" "DI")])
-
-(define_insn "sse_movhlps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (match_operand:V4SF 1 "register_operand" "0")
- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "x")
- (parallel [(const_int 2)
- (const_int 3)
- (const_int 0)
- (const_int 1)]))
- (const_int 3)))]
- "TARGET_SSE"
- "movhlps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse_movlhps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (match_operand:V4SF 1 "register_operand" "0")
- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "x")
- (parallel [(const_int 2)
- (const_int 3)
- (const_int 0)
- (const_int 1)]))
- (const_int 12)))]
- "TARGET_SSE"
- "movlhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse_movhps"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
- (vec_merge:V4SF
- (match_operand:V4SF 1 "nonimmediate_operand" "0,0")
- (match_operand:V4SF 2 "nonimmediate_operand" "m,x")
- (const_int 12)))]
- "TARGET_SSE
- && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
- "movhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse_movlps"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
- (vec_merge:V4SF
- (match_operand:V4SF 1 "nonimmediate_operand" "0,0")
- (match_operand:V4SF 2 "nonimmediate_operand" "m,x")
- (const_int 3)))]
- "TARGET_SSE
- && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
- "movlps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_expand "sse_loadss"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:SF 1 "memory_operand" "")]
- "TARGET_SSE"
-{
- emit_insn (gen_sse_loadss_1 (operands[0], operands[1],
- CONST0_RTX (V4SFmode)));
- DONE;
-})
-
-(define_insn "sse_loadss_1"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (vec_duplicate:V4SF (match_operand:SF 1 "memory_operand" "m"))
- (match_operand:V4SF 2 "const0_operand" "X")
- (const_int 1)))]
- "TARGET_SSE"
- "movss\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "SF")])
-
-(define_insn "sse_movss"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "register_operand" "x")
- (const_int 1)))]
- "TARGET_SSE"
- "movss\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "SF")])
-
-(define_insn "sse_storess"
- [(set (match_operand:SF 0 "memory_operand" "=m")
- (vec_select:SF
- (match_operand:V4SF 1 "register_operand" "x")
- (parallel [(const_int 0)])))]
- "TARGET_SSE"
- "movss\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "SF")])
-
-(define_insn "sse_shufps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")
- (match_operand:SI 3 "immediate_operand" "i")]
- UNSPEC_SHUFFLE))]
- "TARGET_SSE"
- ;; @@@ check operand order for intel/nonintel syntax
- "shufps\t{%3, %2, %0|%0, %2, %3}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-
-;; SSE arithmetic
-
-(define_insn "addv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (plus:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "addps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmaddv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (plus:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE"
- "addss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "SF")])
-
-(define_insn "subv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (minus:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "subps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmsubv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (minus:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE"
- "subss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "SF")])
-
-(define_insn "mulv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (mult:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "mulps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssemul")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmmulv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (mult:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE"
- "mulss\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssemul")
- (set_attr "mode" "SF")])
-
-(define_insn "divv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (div:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "divps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssediv")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmdivv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (div:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE"
- "divss\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssediv")
- (set_attr "mode" "SF")])
-
-
-;; SSE square root/reciprocal
-
-(define_insn "rcpv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF
- [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RCP))]
- "TARGET_SSE"
- "rcpps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmrcpv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
- UNSPEC_RCP)
- (match_operand:V4SF 2 "register_operand" "0")
- (const_int 1)))]
- "TARGET_SSE"
- "rcpss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "SF")])
-
-(define_insn "rsqrtv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF
- [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RSQRT))]
- "TARGET_SSE"
- "rsqrtps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmrsqrtv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
- UNSPEC_RSQRT)
- (match_operand:V4SF 2 "register_operand" "0")
- (const_int 1)))]
- "TARGET_SSE"
- "rsqrtss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "SF")])
-
-(define_insn "sqrtv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "sqrtps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmsqrtv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "xm"))
- (match_operand:V4SF 2 "register_operand" "0")
- (const_int 1)))]
- "TARGET_SSE"
- "sqrtss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "SF")])
-
-;; SSE logical operations.
-
-;; SSE defines logical operations on floating point values. This brings
-;; interesting challenge to RTL representation where logicals are only valid
-;; on integral types. We deal with this by representing the floating point
-;; logical as logical on arguments casted to TImode as this is what hardware
-;; really does. Unfortunately hardware requires the type information to be
-;; present and thus we must avoid subregs from being simplified and eliminated
-;; in later compilation phases.
-;;
-;; We have following variants from each instruction:
-;; sse_andsf3 - the operation taking V4SF vector operands
-;; and doing TImode cast on them
-;; *sse_andsf3_memory - the operation taking one memory operand casted to
-;; TImode, since backend insist on eliminating casts
-;; on memory operands
-;; sse_andti3_sf_1 - the operation taking SF scalar operands.
-;; We can not accept memory operand here as instruction reads
-;; whole scalar. This is generated only post reload by GCC
-;; scalar float operations that expands to logicals (fabs)
-;; sse_andti3_sf_2 - the operation taking SF scalar input and TImode
-;; memory operand. Eventually combine can be able
-;; to synthesize these using splitter.
-;; sse2_anddf3, *sse2_anddf3_memory
-;;
-;;
-;; These are not called andti3 etc. because we really really don't want
-;; the compiler to widen DImode ands to TImode ands and then try to move
-;; into DImode subregs of SSE registers, and them together, and move out
-;; of DImode subregs again!
-;; SSE1 single precision floating point logical operation
-(define_expand "sse_andv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (and:V4SF (match_operand:V4SF 1 "register_operand" "")
- (match_operand:V4SF 2 "nonimmediate_operand" "")))]
- "TARGET_SSE"
- "")
-
-(define_insn "*sse_andv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (and:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "andps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V4SF")])
-
-(define_expand "sse_nandv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (and:V4SF (not:V4SF (match_operand:V4SF 1 "register_operand" ""))
- (match_operand:V4SF 2 "nonimmediate_operand" "")))]
- "TARGET_SSE"
- "")
-
-(define_insn "*sse_nandv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (and:V4SF (not:V4SF (match_operand:V4SF 1 "register_operand" "0"))
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "andnps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V4SF")])
-
-(define_expand "sse_iorv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (ior:V4SF (match_operand:V4SF 1 "register_operand" "")
- (match_operand:V4SF 2 "nonimmediate_operand" "")))]
- "TARGET_SSE"
- "")
-
-(define_insn "*sse_iorv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (ior:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "orps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V4SF")])
-
-(define_expand "sse_xorv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (xor:V4SF (match_operand:V4SF 1 "register_operand" "")
- (match_operand:V4SF 2 "nonimmediate_operand" "")))]
- "TARGET_SSE"
- "")
-
-(define_insn "*sse_xorv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (xor:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "xorps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V4SF")])
-
-;; SSE2 double precision floating point logical operation
-
-(define_expand "sse2_andv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "")
- (and:V2DF (match_operand:V2DF 1 "register_operand" "")
- (match_operand:V2DF 2 "nonimmediate_operand" "")))]
- "TARGET_SSE2"
- "")
-
-(define_insn "*sse2_andv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (and:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "andpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V2DF")])
-
-(define_expand "sse2_nandv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "")
- (and:V2DF (not:V2DF (match_operand:V2DF 1 "register_operand" ""))
- (match_operand:V2DF 2 "nonimmediate_operand" "")))]
- "TARGET_SSE2"
- "")
-
-(define_insn "*sse2_nandv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (and:V2DF (not:V2DF (match_operand:V2DF 1 "register_operand" "0"))
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "andnpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V2DF")])
-
-(define_expand "sse2_iorv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "")
- (ior:V2DF (match_operand:V2DF 1 "register_operand" "")
- (match_operand:V2DF 2 "nonimmediate_operand" "")))]
- "TARGET_SSE2"
- "")
-
-(define_insn "*sse2_iorv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (ior:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "orpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V2DF")])
-
-(define_expand "sse2_xorv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "")
- (xor:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
- (match_operand:V2DF 2 "nonimmediate_operand" "")))]
- "TARGET_SSE2"
- "")
-
-(define_insn "*sse2_xorv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (xor:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "xorpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V2DF")])
-
-;; SSE2 integral logicals. These patterns must always come after floating
-;; point ones since we don't want compiler to use integer opcodes on floating
-;; point SSE values to avoid matching of subregs in the match_operand.
-(define_insn "*sse2_andti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
- (match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "pand\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_andv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (and:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0")
- (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "pand\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "TI")])
-
-(define_insn "*sse2_nandti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (and:TI (not:TI (match_operand:TI 1 "register_operand" "0"))
- (match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pandn\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_nandv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (and:V2DI (not:V2DI (match_operand:V2DI 1 "register_operand" "0"))
- (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "pandn\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "TI")])
-
-(define_insn "*sse2_iorti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
- (match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "por\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_iorv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (ior:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0")
- (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "por\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "TI")])
-
-(define_insn "*sse2_xorti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
- (match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "pxor\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_xorv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (xor:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0")
- (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
- && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "pxor\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "TI")])
-
-;; Use xor, but don't show input operands so they aren't live before
-;; this insn.
-(define_insn "sse_clrv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (match_operand:V4SF 1 "const0_operand" "X"))]
- "TARGET_SSE"
-{
- if (get_attr_mode (insn) == MODE_TI)
- return "pxor\t{%0, %0|%0, %0}";
- else
- return "xorps\t{%0, %0|%0, %0}";
-}
- [(set_attr "type" "sselog")
- (set_attr "memory" "none")
- (set (attr "mode")
- (if_then_else
- (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR")
- (const_int 0))
- (ne (symbol_ref "TARGET_SSE2")
- (const_int 0)))
- (eq (symbol_ref "optimize_size")
- (const_int 0)))
- (const_string "TI")
- (const_string "V4SF")))])
-
-;; Use xor, but don't show input operands so they aren't live before
-;; this insn.
-(define_insn "sse_clrv2df"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (unspec:V2DF [(const_int 0)] UNSPEC_NOP))]
- "TARGET_SSE2"
- "xorpd\t{%0, %0|%0, %0}"
- [(set_attr "type" "sselog")
- (set_attr "memory" "none")
- (set_attr "mode" "V4SF")])
-
-;; SSE mask-generating compares
-
-(define_insn "maskcmpv4sf3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (match_operator:V4SI 3 "sse_comparison_operator"
- [(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "register_operand" "x")]))]
- "TARGET_SSE"
- "cmp%D3ps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "V4SF")])
-
-(define_insn "maskncmpv4sf3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (not:V4SI
- (match_operator:V4SI 3 "sse_comparison_operator"
- [(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "register_operand" "x")])))]
- "TARGET_SSE"
-{
- if (GET_CODE (operands[3]) == UNORDERED)
- return "cmpordps\t{%2, %0|%0, %2}";
- else
- return "cmpn%D3ps\t{%2, %0|%0, %2}";
-}
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmmaskcmpv4sf3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (vec_merge:V4SI
- (match_operator:V4SI 3 "sse_comparison_operator"
- [(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "register_operand" "x")])
- (subreg:V4SI (match_dup 1) 0)
- (const_int 1)))]
- "TARGET_SSE"
- "cmp%D3ss\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "SF")])
-
-(define_insn "vmmaskncmpv4sf3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (vec_merge:V4SI
- (not:V4SI
- (match_operator:V4SI 3 "sse_comparison_operator"
- [(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "register_operand" "x")]))
- (subreg:V4SI (match_dup 1) 0)
- (const_int 1)))]
- "TARGET_SSE"
-{
- if (GET_CODE (operands[3]) == UNORDERED)
- return "cmpordss\t{%2, %0|%0, %2}";
- else
- return "cmpn%D3ss\t{%2, %0|%0, %2}";
-}
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "SF")])
-
-(define_insn "sse_comi"
- [(set (reg:CCFP 17)
- (compare:CCFP (vec_select:SF
- (match_operand:V4SF 0 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:SF
- (match_operand:V4SF 1 "register_operand" "x")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE"
- "comiss\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecomi")
- (set_attr "mode" "SF")])
-
-(define_insn "sse_ucomi"
- [(set (reg:CCFPU 17)
- (compare:CCFPU (vec_select:SF
- (match_operand:V4SF 0 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:SF
- (match_operand:V4SF 1 "register_operand" "x")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE"
- "ucomiss\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecomi")
- (set_attr "mode" "SF")])
-
-
-;; SSE unpack
-
-(define_insn "sse_unpckhps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "x")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
- "TARGET_SSE"
- "unpckhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse_unpcklps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "x")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (const_int 5)))]
- "TARGET_SSE"
- "unpcklps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-
-;; SSE min/max
-
-(define_insn "smaxv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (smax:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "maxps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmsmaxv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (smax:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE"
- "maxss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
- (set_attr "mode" "SF")])
-
-(define_insn "sminv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (smin:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "minps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
- (set_attr "mode" "V4SF")])
-
-(define_insn "vmsminv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (smin:V4SF (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE"
- "minss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
- (set_attr "mode" "SF")])
-
-;; SSE <-> integer/MMX conversions
-
-(define_insn "cvtpi2ps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (match_operand:V4SF 1 "register_operand" "0")
- (vec_duplicate:V4SF
- (float:V2SF (match_operand:V2SI 2 "nonimmediate_operand" "ym")))
- (const_int 12)))]
- "TARGET_SSE"
- "cvtpi2ps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "cvtps2pi"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_select:V2SI
- (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm"))
- (parallel [(const_int 0) (const_int 1)])))]
- "TARGET_SSE"
- "cvtps2pi\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "cvttps2pi"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_select:V2SI
- (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
- UNSPEC_FIX)
- (parallel [(const_int 0) (const_int 1)])))]
- "TARGET_SSE"
- "cvttps2pi\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "SF")])
-
-(define_insn "cvtsi2ss"
- [(set (match_operand:V4SF 0 "register_operand" "=x,x")
- (vec_merge:V4SF
- (match_operand:V4SF 1 "register_operand" "0,0")
- (vec_duplicate:V4SF
- (float:SF (match_operand:SI 2 "nonimmediate_operand" "r,rm")))
- (const_int 14)))]
- "TARGET_SSE"
- "cvtsi2ss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "vector,double")
- (set_attr "mode" "SF")])
-
-(define_insn "cvtsi2ssq"
- [(set (match_operand:V4SF 0 "register_operand" "=x,x")
- (vec_merge:V4SF
- (match_operand:V4SF 1 "register_operand" "0,0")
- (vec_duplicate:V4SF
- (float:SF (match_operand:DI 2 "nonimmediate_operand" "r,rm")))
- (const_int 14)))]
- "TARGET_SSE && TARGET_64BIT"
- "cvtsi2ssq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "vector,double")
- (set_attr "mode" "SF")])
-
-(define_insn "cvtss2si"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (vec_select:SI
- (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "x,m"))
- (parallel [(const_int 0)])))]
- "TARGET_SSE"
- "cvtss2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "double,vector")
- (set_attr "mode" "SI")])
-
-(define_insn "cvtss2siq"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (vec_select:DI
- (fix:V4DI (match_operand:V4SF 1 "nonimmediate_operand" "x,m"))
- (parallel [(const_int 0)])))]
- "TARGET_SSE"
- "cvtss2siq\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "double,vector")
- (set_attr "mode" "DI")])
-
-(define_insn "cvttss2si"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (vec_select:SI
- (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "x,xm")]
- UNSPEC_FIX)
- (parallel [(const_int 0)])))]
- "TARGET_SSE"
- "cvttss2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "SF")
- (set_attr "athlon_decode" "double,vector")])
-
-(define_insn "cvttss2siq"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (vec_select:DI
- (unspec:V4DI [(match_operand:V4SF 1 "nonimmediate_operand" "x,xm")]
- UNSPEC_FIX)
- (parallel [(const_int 0)])))]
- "TARGET_SSE && TARGET_64BIT"
- "cvttss2siq\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "SF")
- (set_attr "athlon_decode" "double,vector")])
-
-
-;; MMX insns
-
-;; MMX arithmetic
-
-(define_insn "addv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (plus:V8QI (match_operand:V8QI 1 "register_operand" "%0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "paddb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "addv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (plus:V4HI (match_operand:V4HI 1 "register_operand" "%0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "paddw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "addv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (plus:V2SI (match_operand:V2SI 1 "register_operand" "%0")
- (match_operand:V2SI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "paddd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_adddi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI
- [(plus:DI (match_operand:DI 1 "register_operand" "%0")
- (match_operand:DI 2 "nonimmediate_operand" "ym"))]
- UNSPEC_NOP))]
- "TARGET_MMX"
- "paddq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "ssaddv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (ss_plus:V8QI (match_operand:V8QI 1 "register_operand" "%0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "paddsb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "ssaddv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ss_plus:V4HI (match_operand:V4HI 1 "register_operand" "%0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "paddsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "usaddv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (us_plus:V8QI (match_operand:V8QI 1 "register_operand" "%0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "paddusb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "usaddv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (us_plus:V4HI (match_operand:V4HI 1 "register_operand" "%0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "paddusw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "subv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (minus:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "psubb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "subv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (minus:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "psubw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "subv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (minus:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (match_operand:V2SI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "psubd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_subdi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI
- [(minus:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonimmediate_operand" "ym"))]
- UNSPEC_NOP))]
- "TARGET_MMX"
- "psubq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "sssubv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (ss_minus:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "psubsb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "sssubv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ss_minus:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "psubsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "ussubv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (us_minus:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "psubusb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "ussubv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (us_minus:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "psubusw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "mulv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (mult:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pmullw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
-
-(define_insn "smulv4hi3_highpart"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (truncate:V4HI
- (lshiftrt:V4SI
- (mult:V4SI (sign_extend:V4SI
- (match_operand:V4HI 1 "register_operand" "0"))
- (sign_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
- (const_int 16))))]
- "TARGET_MMX"
- "pmulhw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
-
-(define_insn "umulv4hi3_highpart"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (truncate:V4HI
- (lshiftrt:V4SI
- (mult:V4SI (zero_extend:V4SI
- (match_operand:V4HI 1 "register_operand" "0"))
- (zero_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
- (const_int 16))))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pmulhuw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_pmaddwd"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (plus:V2SI
- (mult:V2SI
- (sign_extend:V2SI
- (vec_select:V2HI (match_operand:V4HI 1 "register_operand" "0")
- (parallel [(const_int 0) (const_int 2)])))
- (sign_extend:V2SI
- (vec_select:V2HI (match_operand:V4HI 2 "nonimmediate_operand" "ym")
- (parallel [(const_int 0) (const_int 2)]))))
- (mult:V2SI
- (sign_extend:V2SI (vec_select:V2HI (match_dup 1)
- (parallel [(const_int 1)
- (const_int 3)])))
- (sign_extend:V2SI (vec_select:V2HI (match_dup 2)
- (parallel [(const_int 1)
- (const_int 3)]))))))]
- "TARGET_MMX"
- "pmaddwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
-
-
-;; MMX logical operations
-;; Note we don't want to declare these as regular iordi3 insns to prevent
-;; normal code that also wants to use the FPU from getting broken.
-;; The UNSPECs are there to prevent the combiner from getting overly clever.
-(define_insn "mmx_iordi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI
- [(ior:DI (match_operand:DI 1 "register_operand" "%0")
- (match_operand:DI 2 "nonimmediate_operand" "ym"))]
- UNSPEC_NOP))]
- "TARGET_MMX"
- "por\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_xordi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI
- [(xor:DI (match_operand:DI 1 "register_operand" "%0")
- (match_operand:DI 2 "nonimmediate_operand" "ym"))]
- UNSPEC_NOP))]
- "TARGET_MMX"
- "pxor\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")
- (set_attr "memory" "none")])
-
-;; Same as pxor, but don't show input operands so that we don't think
-;; they are live.
-(define_insn "mmx_clrdi"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(const_int 0)] UNSPEC_NOP))]
- "TARGET_MMX"
- "pxor\t{%0, %0|%0, %0}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")
- (set_attr "memory" "none")])
-
-(define_insn "mmx_anddi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI
- [(and:DI (match_operand:DI 1 "register_operand" "%0")
- (match_operand:DI 2 "nonimmediate_operand" "ym"))]
- UNSPEC_NOP))]
- "TARGET_MMX"
- "pand\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_nanddi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI
- [(and:DI (not:DI (match_operand:DI 1 "register_operand" "0"))
- (match_operand:DI 2 "nonimmediate_operand" "ym"))]
- UNSPEC_NOP))]
- "TARGET_MMX"
- "pandn\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-
-;; MMX unsigned averages/sum of absolute differences
-
-(define_insn "mmx_uavgv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (ashiftrt:V8QI
- (plus:V8QI (plus:V8QI
- (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym"))
- (const_vector:V8QI [(const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)]))
- (const_int 1)))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pavgb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_uavgv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashiftrt:V4HI
- (plus:V4HI (plus:V4HI
- (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym"))
- (const_vector:V4HI [(const_int 1)
- (const_int 1)
- (const_int 1)
- (const_int 1)]))
- (const_int 1)))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pavgw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_psadbw"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
- UNSPEC_PSADBW))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "psadbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-
-;; MMX insert/extract/shuffle
-
-(define_insn "mmx_pinsrw"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_merge:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (vec_duplicate:V4HI
- (truncate:HI (match_operand:SI 2 "nonimmediate_operand" "rm")))
- (match_operand:SI 3 "const_0_to_15_operand" "N")))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pinsrw\t{%3, %2, %0|%0, %2, %3}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_pextrw"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI (vec_select:HI (match_operand:V4HI 1 "register_operand" "y")
- (parallel
- [(match_operand:SI 2 "const_0_to_3_operand" "N")]))))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pextrw\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_pshufw"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "0")
- (match_operand:SI 2 "immediate_operand" "i")]
- UNSPEC_SHUFFLE))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pshufw\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-
-;; MMX mask-generating comparisons
-
-(define_insn "eqv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (eq:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pcmpeqb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "DI")])
-
-(define_insn "eqv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (eq:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pcmpeqw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "DI")])
-
-(define_insn "eqv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (eq:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (match_operand:V2SI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pcmpeqd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "DI")])
-
-(define_insn "gtv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (gt:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pcmpgtb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "DI")])
-
-(define_insn "gtv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (gt:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pcmpgtw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "DI")])
-
-(define_insn "gtv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (gt:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (match_operand:V2SI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pcmpgtd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "DI")])
-
-
-;; MMX max/min insns
-
-(define_insn "umaxv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (umax:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pmaxub\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "smaxv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (smax:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pmaxsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "uminv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (umin:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pminub\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-(define_insn "sminv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (smin:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pminsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
-
-
-;; MMX shifts
-
-(define_insn "ashrv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashiftrt:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
- "TARGET_MMX"
- "psraw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "ashrv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ashiftrt:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
- "TARGET_MMX"
- "psrad\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "lshrv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (lshiftrt:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
- "TARGET_MMX"
- "psrlw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "lshrv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (lshiftrt:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
- "TARGET_MMX"
- "psrld\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-;; See logical MMX insns.
-(define_insn "mmx_lshrdi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI
- [(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi"))]
- UNSPEC_NOP))]
- "TARGET_MMX"
- "psrlq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "ashlv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (ashift:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
- "TARGET_MMX"
- "psllw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "ashlv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ashift:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
- "TARGET_MMX"
- "pslld\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-;; See logical MMX insns.
-(define_insn "mmx_ashldi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI
- [(ashift:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi"))]
- UNSPEC_NOP))]
- "TARGET_MMX"
- "psllq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-
-;; MMX pack/unpack insns.
-
-(define_insn "mmx_packsswb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_concat:V8QI
- (ss_truncate:V4QI (match_operand:V4HI 1 "register_operand" "0"))
- (ss_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))]
- "TARGET_MMX"
- "packsswb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_packssdw"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_concat:V4HI
- (ss_truncate:V2HI (match_operand:V2SI 1 "register_operand" "0"))
- (ss_truncate:V2HI (match_operand:V2SI 2 "register_operand" "y"))))]
- "TARGET_MMX"
- "packssdw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_packuswb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_concat:V8QI
- (us_truncate:V4QI (match_operand:V4HI 1 "register_operand" "0"))
- (us_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))]
- "TARGET_MMX"
- "packuswb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_punpckhbw"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_merge:V8QI
- (vec_select:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (parallel [(const_int 4)
- (const_int 0)
- (const_int 5)
- (const_int 1)
- (const_int 6)
- (const_int 2)
- (const_int 7)
- (const_int 3)]))
- (vec_select:V8QI (match_operand:V8QI 2 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 4)
- (const_int 1)
- (const_int 5)
- (const_int 2)
- (const_int 6)
- (const_int 3)
- (const_int 7)]))
- (const_int 85)))]
- "TARGET_MMX"
- "punpckhbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_punpckhwd"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_merge:V4HI
- (vec_select:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (vec_select:V4HI (match_operand:V4HI 2 "register_operand" "y")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (const_int 5)))]
- "TARGET_MMX"
- "punpckhwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_punpckhdq"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_merge:V2SI
- (match_operand:V2SI 1 "register_operand" "0")
- (vec_select:V2SI (match_operand:V2SI 2 "register_operand" "y")
- (parallel [(const_int 1)
- (const_int 0)]))
- (const_int 1)))]
- "TARGET_MMX"
- "punpckhdq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_punpcklbw"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_merge:V8QI
- (vec_select:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (parallel [(const_int 0)
- (const_int 4)
- (const_int 1)
- (const_int 5)
- (const_int 2)
- (const_int 6)
- (const_int 3)
- (const_int 7)]))
- (vec_select:V8QI (match_operand:V8QI 2 "register_operand" "y")
- (parallel [(const_int 4)
- (const_int 0)
- (const_int 5)
- (const_int 1)
- (const_int 6)
- (const_int 2)
- (const_int 7)
- (const_int 3)]))
- (const_int 85)))]
- "TARGET_MMX"
- "punpcklbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_punpcklwd"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (vec_merge:V4HI
- (vec_select:V4HI (match_operand:V4HI 1 "register_operand" "0")
- (parallel [(const_int 2)
- (const_int 0)
- (const_int 3)
- (const_int 1)]))
- (vec_select:V4HI (match_operand:V4HI 2 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 1)
- (const_int 3)]))
- (const_int 5)))]
- "TARGET_MMX"
- "punpcklwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_punpckldq"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_merge:V2SI
- (vec_select:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (parallel [(const_int 1)
- (const_int 0)]))
- (match_operand:V2SI 2 "register_operand" "y")
- (const_int 1)))]
- "TARGET_MMX"
- "punpckldq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
-
-
-;; Miscellaneous stuff
-
-(define_insn "emms"
- [(unspec_volatile [(const_int 0)] UNSPECV_EMMS)
- (clobber (reg:XF 8))
- (clobber (reg:XF 9))
- (clobber (reg:XF 10))
- (clobber (reg:XF 11))
- (clobber (reg:XF 12))
- (clobber (reg:XF 13))
- (clobber (reg:XF 14))
- (clobber (reg:XF 15))
- (clobber (reg:DI 29))
- (clobber (reg:DI 30))
- (clobber (reg:DI 31))
- (clobber (reg:DI 32))
- (clobber (reg:DI 33))
- (clobber (reg:DI 34))
- (clobber (reg:DI 35))
- (clobber (reg:DI 36))]
- "TARGET_MMX"
- "emms"
- [(set_attr "type" "mmx")
- (set_attr "memory" "unknown")])
-
-(define_insn "ldmxcsr"
- [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")]
- UNSPECV_LDMXCSR)]
- "TARGET_SSE"
- "ldmxcsr\t%0"
- [(set_attr "type" "sse")
- (set_attr "memory" "load")])
-
-(define_insn "stmxcsr"
- [(set (match_operand:SI 0 "memory_operand" "=m")
- (unspec_volatile:SI [(const_int 0)] UNSPECV_STMXCSR))]
- "TARGET_SSE"
- "stmxcsr\t%0"
- [(set_attr "type" "sse")
- (set_attr "memory" "store")])
-
-(define_expand "sfence"
- [(set (match_dup 0)
- (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
- "TARGET_SSE || TARGET_3DNOW_A"
-{
- operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
- MEM_VOLATILE_P (operands[0]) = 1;
-})
-
-(define_insn "*sfence_insn"
- [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "sfence"
- [(set_attr "type" "sse")
- (set_attr "memory" "unknown")])
+ { return ASM_SHORT "0x0b0f"; }
+ [(set_attr "length" "2")])
(define_expand "sse_prologue_save"
[(parallel [(set (match_operand:BLK 0 "" "")
@@ -20919,311 +20718,6 @@
(set_attr "modrm" "0")
(set_attr "mode" "DI")])
-;; 3Dnow! instructions
-
-(define_insn "addv2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (plus:V2SF (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pfadd\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "V2SF")])
-
-(define_insn "subv2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (minus:V2SF (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pfsub\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "V2SF")])
-
-(define_insn "subrv2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (minus:V2SF (match_operand:V2SF 2 "nonimmediate_operand" "ym")
- (match_operand:V2SF 1 "register_operand" "0")))]
- "TARGET_3DNOW"
- "pfsubr\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "V2SF")])
-
-(define_insn "gtv2sf3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (gt:V2SI (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pfcmpgt\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "V2SF")])
-
-(define_insn "gev2sf3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (ge:V2SI (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pfcmpge\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "V2SF")])
-
-(define_insn "eqv2sf3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (eq:V2SI (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pfcmpeq\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "V2SF")])
-
-(define_insn "pfmaxv2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (smax:V2SF (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pfmax\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "V2SF")])
-
-(define_insn "pfminv2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (smin:V2SF (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pfmin\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "V2SF")])
-
-(define_insn "mulv2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (mult:V2SF (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pfmul\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "V2SF")])
-
-(define_insn "femms"
- [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS)
- (clobber (reg:XF 8))
- (clobber (reg:XF 9))
- (clobber (reg:XF 10))
- (clobber (reg:XF 11))
- (clobber (reg:XF 12))
- (clobber (reg:XF 13))
- (clobber (reg:XF 14))
- (clobber (reg:XF 15))
- (clobber (reg:DI 29))
- (clobber (reg:DI 30))
- (clobber (reg:DI 31))
- (clobber (reg:DI 32))
- (clobber (reg:DI 33))
- (clobber (reg:DI 34))
- (clobber (reg:DI 35))
- (clobber (reg:DI 36))]
- "TARGET_3DNOW"
- "femms"
- [(set_attr "type" "mmx")
- (set_attr "memory" "none")])
-
-(define_insn "pf2id"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pf2id\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "V2SF")])
-
-(define_insn "pf2iw"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (sign_extend:V2SI
- (ss_truncate:V2HI
- (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))))]
- "TARGET_3DNOW_A"
- "pf2iw\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "V2SF")])
-
-(define_insn "pfacc"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (vec_concat:V2SF
- (plus:SF
- (vec_select:SF (match_operand:V2SF 1 "register_operand" "0")
- (parallel [(const_int 0)]))
- (vec_select:SF (match_dup 1)
- (parallel [(const_int 1)])))
- (plus:SF
- (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y")
- (parallel [(const_int 0)]))
- (vec_select:SF (match_dup 2)
- (parallel [(const_int 1)])))))]
- "TARGET_3DNOW"
- "pfacc\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "V2SF")])
-
-(define_insn "pfnacc"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (vec_concat:V2SF
- (minus:SF
- (vec_select:SF (match_operand:V2SF 1 "register_operand" "0")
- (parallel [(const_int 0)]))
- (vec_select:SF (match_dup 1)
- (parallel [(const_int 1)])))
- (minus:SF
- (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y")
- (parallel [(const_int 0)]))
- (vec_select:SF (match_dup 2)
- (parallel [(const_int 1)])))))]
- "TARGET_3DNOW_A"
- "pfnacc\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "V2SF")])
-
-(define_insn "pfpnacc"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (vec_concat:V2SF
- (minus:SF
- (vec_select:SF (match_operand:V2SF 1 "register_operand" "0")
- (parallel [(const_int 0)]))
- (vec_select:SF (match_dup 1)
- (parallel [(const_int 1)])))
- (plus:SF
- (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y")
- (parallel [(const_int 0)]))
- (vec_select:SF (match_dup 2)
- (parallel [(const_int 1)])))))]
- "TARGET_3DNOW_A"
- "pfpnacc\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "V2SF")])
-
-(define_insn "pi2fw"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (float:V2SF
- (vec_concat:V2SI
- (sign_extend:SI
- (truncate:HI
- (vec_select:SI (match_operand:V2SI 1 "nonimmediate_operand" "ym")
- (parallel [(const_int 0)]))))
- (sign_extend:SI
- (truncate:HI
- (vec_select:SI (match_dup 1)
- (parallel [(const_int 1)])))))))]
- "TARGET_3DNOW_A"
- "pi2fw\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "V2SF")])
-
-(define_insn "floatv2si2"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (float:V2SF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW"
- "pi2fd\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "V2SF")])
-
-;; This insn is identical to pavgb in operation, but the opcode is
-;; different. To avoid accidentally matching pavgb, use an unspec.
-
-(define_insn "pavgusb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (unspec:V8QI
- [(match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
- UNSPEC_PAVGUSB))]
- "TARGET_3DNOW"
- "pavgusb\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "TI")])
-
-;; 3DNow reciprocal and sqrt
-
-(define_insn "pfrcpv2sf2"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
- UNSPEC_PFRCP))]
- "TARGET_3DNOW"
- "pfrcp\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")
- (set_attr "mode" "TI")])
-
-(define_insn "pfrcpit1v2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
- UNSPEC_PFRCPIT1))]
- "TARGET_3DNOW"
- "pfrcpit1\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")
- (set_attr "mode" "TI")])
-
-(define_insn "pfrcpit2v2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
- UNSPEC_PFRCPIT2))]
- "TARGET_3DNOW"
- "pfrcpit2\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")
- (set_attr "mode" "TI")])
-
-(define_insn "pfrsqrtv2sf2"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
- UNSPEC_PFRSQRT))]
- "TARGET_3DNOW"
- "pfrsqrt\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")
- (set_attr "mode" "TI")])
-
-(define_insn "pfrsqit1v2sf3"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
- UNSPEC_PFRSQIT1))]
- "TARGET_3DNOW"
- "pfrsqit1\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")
- (set_attr "mode" "TI")])
-
-(define_insn "pmulhrwv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (truncate:V4HI
- (lshiftrt:V4SI
- (plus:V4SI
- (mult:V4SI
- (sign_extend:V4SI
- (match_operand:V4HI 1 "register_operand" "0"))
- (sign_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
- (const_vector:V4SI [(const_int 32768)
- (const_int 32768)
- (const_int 32768)
- (const_int 32768)]))
- (const_int 16))))]
- "TARGET_3DNOW"
- "pmulhrw\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "TI")])
-
-(define_insn "pswapdv2si2"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (vec_select:V2SI (match_operand:V2SI 1 "nonimmediate_operand" "ym")
- (parallel [(const_int 1) (const_int 0)])))]
- "TARGET_3DNOW_A"
- "pswapd\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "TI")])
-
-(define_insn "pswapdv2sf2"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
- (vec_select:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "ym")
- (parallel [(const_int 1) (const_int 0)])))]
- "TARGET_3DNOW_A"
- "pswapd\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "TI")])
-
(define_expand "prefetch"
[(prefetch (match_operand 0 "address_operand" "")
(match_operand:SI 1 "const_int_operand" "")
@@ -21233,15 +20727,13 @@
int rw = INTVAL (operands[1]);
int locality = INTVAL (operands[2]);
- if (rw != 0 && rw != 1)
- abort ();
- if (locality < 0 || locality > 3)
- abort ();
- if (GET_MODE (operands[0]) != Pmode && GET_MODE (operands[0]) != VOIDmode)
- abort ();
+ gcc_assert (rw == 0 || rw == 1);
+ gcc_assert (locality >= 0 && locality <= 3);
+ gcc_assert (GET_MODE (operands[0]) == Pmode
+ || GET_MODE (operands[0]) == VOIDmode);
/* Use 3dNOW prefetch in case we are asking for write prefetch not
- suported by SSE counterpart or the SSE prefetch is not available
+ supported by SSE counterpart or the SSE prefetch is not available
(K6 machines). Otherwise use SSE prefetch as it allows specifying
of locality. */
if (TARGET_3DNOW && (!TARGET_PREFETCH_SSE || rw))
@@ -21261,8 +20753,7 @@
};
int locality = INTVAL (operands[1]);
- if (locality < 0 || locality > 3)
- abort ();
+ gcc_assert (locality >= 0 && locality <= 3);
return patterns[locality];
}
@@ -21280,8 +20771,7 @@
};
int locality = INTVAL (operands[1]);
- if (locality < 0 || locality > 3)
- abort ();
+ gcc_assert (locality >= 0 && locality <= 3);
return patterns[locality];
}
@@ -21316,1706 +20806,147 @@
[(set_attr "type" "mmx")
(set_attr "memory" "none")])
-;; SSE2 support
-
-(define_insn "addv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (plus:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "addpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V2DF")])
-
-(define_insn "vmaddv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF (plus:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE2"
- "addsd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "DF")])
-
-(define_insn "subv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (minus:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "subpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V2DF")])
-
-(define_insn "vmsubv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF (minus:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE2"
- "subsd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "DF")])
-
-(define_insn "mulv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (mult:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "mulpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssemul")
- (set_attr "mode" "V2DF")])
-
-(define_insn "vmmulv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF (mult:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE2"
- "mulsd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssemul")
- (set_attr "mode" "DF")])
-
-(define_insn "divv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (div:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "divpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssediv")
- (set_attr "mode" "V2DF")])
-
-(define_insn "vmdivv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF (div:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE2"
- "divsd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssediv")
- (set_attr "mode" "DF")])
-
-;; SSE min/max
-
-(define_insn "smaxv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (smax:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "maxpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V2DF")])
-
-(define_insn "vmsmaxv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF (smax:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE2"
- "maxsd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "DF")])
-
-(define_insn "sminv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (smin:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "minpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V2DF")])
-
-(define_insn "vmsminv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF (smin:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE2"
- "minsd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "DF")])
-;; SSE2 square root. There doesn't appear to be an extension for the
-;; reciprocal/rsqrt instructions if the Intel manual is to be believed.
-
-(define_insn "sqrtv2df2"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "xm")))]
- "TARGET_SSE2"
- "sqrtpd\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "V2DF")])
-
-(define_insn "vmsqrtv2df2"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "xm"))
- (match_operand:V2DF 2 "register_operand" "0")
- (const_int 1)))]
- "TARGET_SSE2"
- "sqrtsd\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "SF")])
-
-;; SSE mask-generating compares
-
-(define_insn "maskcmpv2df3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (match_operator:V2DI 3 "sse_comparison_operator"
- [(match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "x")]))]
- "TARGET_SSE2"
- "cmp%D3pd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "V2DF")])
-
-(define_insn "maskncmpv2df3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (not:V2DI
- (match_operator:V2DI 3 "sse_comparison_operator"
- [(match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "x")])))]
- "TARGET_SSE2"
+(define_expand "stack_protect_set"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")]
+ ""
{
- if (GET_CODE (operands[3]) == UNORDERED)
- return "cmpordps\t{%2, %0|%0, %2}";
+#ifdef TARGET_THREAD_SSP_OFFSET
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_tls_protect_set_di (operands[0],
+ GEN_INT (TARGET_THREAD_SSP_OFFSET)));
else
- return "cmpn%D3pd\t{%2, %0|%0, %2}";
-}
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "V2DF")])
-
-(define_insn "vmmaskcmpv2df3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (vec_merge:V2DI
- (match_operator:V2DI 3 "sse_comparison_operator"
- [(match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "x")])
- (subreg:V2DI (match_dup 1) 0)
- (const_int 1)))]
- "TARGET_SSE2"
- "cmp%D3sd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "DF")])
-
-(define_insn "vmmaskncmpv2df3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (vec_merge:V2DI
- (not:V2DI
- (match_operator:V2DI 3 "sse_comparison_operator"
- [(match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "x")]))
- (subreg:V2DI (match_dup 1) 0)
- (const_int 1)))]
- "TARGET_SSE2"
-{
- if (GET_CODE (operands[3]) == UNORDERED)
- return "cmpordsd\t{%2, %0|%0, %2}";
+ emit_insn (gen_stack_tls_protect_set_si (operands[0],
+ GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+#else
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_protect_set_di (operands[0], operands[1]));
else
- return "cmpn%D3sd\t{%2, %0|%0, %2}";
-}
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "DF")])
-
-(define_insn "sse2_comi"
- [(set (reg:CCFP 17)
- (compare:CCFP (vec_select:DF
- (match_operand:V2DF 0 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:DF
- (match_operand:V2DF 1 "register_operand" "x")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE2"
- "comisd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecomi")
- (set_attr "mode" "DF")])
-
-(define_insn "sse2_ucomi"
- [(set (reg:CCFPU 17)
- (compare:CCFPU (vec_select:DF
- (match_operand:V2DF 0 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:DF
- (match_operand:V2DF 1 "register_operand" "x")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE2"
- "ucomisd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecomi")
- (set_attr "mode" "DF")])
-
-;; SSE Strange Moves.
-
-(define_insn "sse2_movmskpd"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V2DF 1 "register_operand" "x")]
- UNSPEC_MOVMSK))]
- "TARGET_SSE2"
- "movmskpd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-(define_insn "sse2_pmovmskb"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V16QI 1 "register_operand" "x")]
- UNSPEC_MOVMSK))]
- "TARGET_SSE2"
- "pmovmskb\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-(define_insn "sse2_maskmovdqu"
- [(set (mem:V16QI (match_operand:SI 0 "register_operand" "D"))
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x")
- (match_operand:V16QI 2 "register_operand" "x")]
- UNSPEC_MASKMOV))]
- "TARGET_SSE2"
- ;; @@@ check ordering of operands in intel/nonintel syntax
- "maskmovdqu\t{%2, %1|%1, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_maskmovdqu_rex64"
- [(set (mem:V16QI (match_operand:DI 0 "register_operand" "D"))
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x")
- (match_operand:V16QI 2 "register_operand" "x")]
- UNSPEC_MASKMOV))]
- "TARGET_SSE2"
- ;; @@@ check ordering of operands in intel/nonintel syntax
- "maskmovdqu\t{%2, %1|%1, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_movntv2df"
- [(set (match_operand:V2DF 0 "memory_operand" "=m")
- (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "x")]
- UNSPEC_MOVNT))]
- "TARGET_SSE2"
- "movntpd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-(define_insn "sse2_movntv2di"
- [(set (match_operand:V2DI 0 "memory_operand" "=m")
- (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "x")]
- UNSPEC_MOVNT))]
- "TARGET_SSE2"
- "movntdq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
+ emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
+#endif
+ DONE;
+})
-(define_insn "sse2_movntsi"
+(define_insn "stack_protect_set_si"
[(set (match_operand:SI 0 "memory_operand" "=m")
- (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
- UNSPEC_MOVNT))]
- "TARGET_SSE2"
- "movnti\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-;; SSE <-> integer/MMX conversions
-
-;; Conversions between SI and SF
-
-(define_insn "cvtdq2ps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (float:V4SF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "cvtdq2ps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-(define_insn "cvtps2dq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "cvtps2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "cvttps2dq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
- UNSPEC_FIX))]
- "TARGET_SSE2"
- "cvttps2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-;; Conversions between SI and DF
-
-(define_insn "cvtdq2pd"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (float:V2DF (vec_select:V2SI
- (match_operand:V4SI 1 "nonimmediate_operand" "xm")
- (parallel
- [(const_int 0)
- (const_int 1)]))))]
- "TARGET_SSE2"
- "cvtdq2pd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-(define_insn "cvtpd2dq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (vec_concat:V4SI
- (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm"))
- (const_vector:V2SI [(const_int 0) (const_int 0)])))]
- "TARGET_SSE2"
- "cvtpd2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "cvttpd2dq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (vec_concat:V4SI
- (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")]
- UNSPEC_FIX)
- (const_vector:V2SI [(const_int 0) (const_int 0)])))]
- "TARGET_SSE2"
- "cvttpd2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "cvtpd2pi"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "cvtpd2pi\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "cvttpd2pi"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
- (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")]
- UNSPEC_FIX))]
- "TARGET_SSE2"
- "cvttpd2pi\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "cvtpi2pd"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (float:V2DF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))]
- "TARGET_SSE2"
- "cvtpi2pd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-;; Conversions between SI and DF
-
-(define_insn "cvtsd2si"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (fix:SI (vec_select:DF (match_operand:V2DF 1 "register_operand" "x,m")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE2"
- "cvtsd2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "double,vector")
- (set_attr "mode" "SI")])
-
-(define_insn "cvtsd2siq"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (fix:DI (vec_select:DF (match_operand:V2DF 1 "register_operand" "x,m")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE2 && TARGET_64BIT"
- "cvtsd2siq\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "double,vector")
- (set_attr "mode" "DI")])
-
-(define_insn "cvttsd2si"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (unspec:SI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "x,xm")
- (parallel [(const_int 0)]))] UNSPEC_FIX))]
- "TARGET_SSE2"
- "cvttsd2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "SI")
- (set_attr "athlon_decode" "double,vector")])
-
-(define_insn "cvttsd2siq"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (unspec:DI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "x,xm")
- (parallel [(const_int 0)]))] UNSPEC_FIX))]
- "TARGET_SSE2 && TARGET_64BIT"
- "cvttsd2siq\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "DI")
- (set_attr "athlon_decode" "double,vector")])
-
-(define_insn "cvtsi2sd"
- [(set (match_operand:V2DF 0 "register_operand" "=x,x")
- (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0,0")
- (vec_duplicate:V2DF
- (float:DF
- (match_operand:SI 2 "nonimmediate_operand" "r,rm")))
- (const_int 2)))]
- "TARGET_SSE2"
- "cvtsi2sd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "DF")
- (set_attr "athlon_decode" "double,direct")])
-
-(define_insn "cvtsi2sdq"
- [(set (match_operand:V2DF 0 "register_operand" "=x,x")
- (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0,0")
- (vec_duplicate:V2DF
- (float:DF
- (match_operand:DI 2 "nonimmediate_operand" "r,rm")))
- (const_int 2)))]
- "TARGET_SSE2 && TARGET_64BIT"
- "cvtsi2sdq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseicvt")
- (set_attr "mode" "DF")
- (set_attr "athlon_decode" "double,direct")])
-
-;; Conversions between SF and DF
-
-(define_insn "cvtsd2ss"
- [(set (match_operand:V4SF 0 "register_operand" "=x,x")
- (vec_merge:V4SF (match_operand:V4SF 1 "register_operand" "0,0")
- (vec_duplicate:V4SF
- (float_truncate:V2SF
- (match_operand:V2DF 2 "nonimmediate_operand" "x,xm")))
- (const_int 14)))]
- "TARGET_SSE2"
- "cvtsd2ss\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "athlon_decode" "vector,double")
- (set_attr "mode" "SF")])
-
-(define_insn "cvtss2sd"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0")
- (float_extend:V2DF
- (vec_select:V2SF
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)
- (const_int 1)])))
- (const_int 2)))]
- "TARGET_SSE2"
- "cvtss2sd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "DF")])
+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:SI 2 "=&r") (const_int 0))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "mov{l}\t{%1, %2|%2, %1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
+ [(set_attr "type" "multi")])
-(define_insn "cvtpd2ps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (subreg:V4SF
- (vec_concat:V4SI
- (subreg:V2SI (float_truncate:V2SF
- (match_operand:V2DF 1 "nonimmediate_operand" "xm")) 0)
- (const_vector:V2SI [(const_int 0) (const_int 0)])) 0))]
- "TARGET_SSE2"
- "cvtpd2ps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "cvtps2pd"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (float_extend:V2DF
- (vec_select:V2SF (match_operand:V4SF 1 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)
- (const_int 1)]))))]
- "TARGET_SSE2"
- "cvtps2pd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
+(define_insn "stack_protect_set_di"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:DI 2 "=&r") (const_int 0))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "mov{q}\t{%1, %2|%2, %1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
+ [(set_attr "type" "multi")])
-;; SSE2 variants of MMX insns
+(define_insn "stack_tls_protect_set_si"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
+ (set (match_scratch:SI 2 "=&r") (const_int 0))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR %%gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
+ [(set_attr "type" "multi")])
-;; MMX arithmetic
+(define_insn "stack_tls_protect_set_di"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "const_int_operand" "i")] UNSPEC_SP_TLS_SET))
+ (set (match_scratch:DI 2 "=&r") (const_int 0))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ {
+ /* The kernel uses a different segment register for performance reasons; a
+ system call would not have to trash the userspace segment register,
+ which would be expensive */
+ if (ix86_cmodel != CM_KERNEL)
+ return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
+ else
+ return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
+ }
+ [(set_attr "type" "multi")])
-(define_insn "addv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (plus:V16QI (match_operand:V16QI 1 "register_operand" "%0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "paddb\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "addv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (plus:V8HI (match_operand:V8HI 1 "register_operand" "%0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "paddw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "addv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (plus:V4SI (match_operand:V4SI 1 "register_operand" "%0")
- (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "paddd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "addv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (plus:V2DI (match_operand:V2DI 1 "register_operand" "%0")
- (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "paddq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "ssaddv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (ss_plus:V16QI (match_operand:V16QI 1 "register_operand" "%0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "paddsb\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "ssaddv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (ss_plus:V8HI (match_operand:V8HI 1 "register_operand" "%0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "paddsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "usaddv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (us_plus:V16QI (match_operand:V16QI 1 "register_operand" "%0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "paddusb\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "usaddv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (us_plus:V8HI (match_operand:V8HI 1 "register_operand" "%0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "paddusw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "subv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (minus:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "psubb\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "subv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (minus:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "psubw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "subv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (minus:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "psubd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "subv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (minus:V2DI (match_operand:V2DI 1 "register_operand" "0")
- (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "psubq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "sssubv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (ss_minus:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "psubsb\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "sssubv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (ss_minus:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "psubsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "ussubv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (us_minus:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "psubusb\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "ussubv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (us_minus:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "psubusw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "mulv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (mult:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pmullw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseimul")
- (set_attr "mode" "TI")])
-
-(define_insn "smulv8hi3_highpart"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (truncate:V8HI
- (lshiftrt:V8SI
- (mult:V8SI (sign_extend:V8SI (match_operand:V8HI 1 "register_operand" "0"))
- (sign_extend:V8SI (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
- (const_int 16))))]
- "TARGET_SSE2"
- "pmulhw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseimul")
- (set_attr "mode" "TI")])
-
-(define_insn "umulv8hi3_highpart"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (truncate:V8HI
- (lshiftrt:V8SI
- (mult:V8SI (zero_extend:V8SI (match_operand:V8HI 1 "register_operand" "0"))
- (zero_extend:V8SI (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
- (const_int 16))))]
- "TARGET_SSE2"
- "pmulhuw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseimul")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_umulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (mult:DI (zero_extend:DI (vec_select:SI
- (match_operand:V2SI 1 "register_operand" "0")
- (parallel [(const_int 0)])))
- (zero_extend:DI (vec_select:SI
- (match_operand:V2SI 2 "nonimmediate_operand" "ym")
- (parallel [(const_int 0)])))))]
- "TARGET_SSE2"
- "pmuludq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseimul")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_umulv2siv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (mult:V2DI (zero_extend:V2DI
- (vec_select:V2SI
- (match_operand:V4SI 1 "register_operand" "0")
- (parallel [(const_int 0) (const_int 2)])))
- (zero_extend:V2DI
- (vec_select:V2SI
- (match_operand:V4SI 2 "nonimmediate_operand" "xm")
- (parallel [(const_int 0) (const_int 2)])))))]
- "TARGET_SSE2"
- "pmuludq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseimul")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_pmaddwd"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (plus:V4SI
- (mult:V4SI
- (sign_extend:V4SI (vec_select:V4HI (match_operand:V8HI 1 "register_operand" "0")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 4)
- (const_int 6)])))
- (sign_extend:V4SI (vec_select:V4HI (match_operand:V8HI 2 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)
- (const_int 2)
- (const_int 4)
- (const_int 6)]))))
- (mult:V4SI
- (sign_extend:V4SI (vec_select:V4HI (match_dup 1)
- (parallel [(const_int 1)
- (const_int 3)
- (const_int 5)
- (const_int 7)])))
- (sign_extend:V4SI (vec_select:V4HI (match_dup 2)
- (parallel [(const_int 1)
- (const_int 3)
- (const_int 5)
- (const_int 7)]))))))]
- "TARGET_SSE2"
- "pmaddwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-;; Same as pxor, but don't show input operands so that we don't think
-;; they are live.
-(define_insn "sse2_clrti"
- [(set (match_operand:TI 0 "register_operand" "=x") (const_int 0))]
- "TARGET_SSE2"
+(define_expand "stack_protect_test"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")
+ (match_operand 2 "" "")]
+ ""
{
- if (get_attr_mode (insn) == MODE_TI)
- return "pxor\t%0, %0";
- else
- return "xorps\t%0, %0";
-}
- [(set_attr "type" "ssemov")
- (set_attr "memory" "none")
- (set (attr "mode")
- (if_then_else
- (ne (symbol_ref "optimize_size")
- (const_int 0))
- (const_string "V4SF")
- (const_string "TI")))])
-
-;; MMX unsigned averages/sum of absolute differences
-
-(define_insn "sse2_uavgv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (ashiftrt:V16QI
- (plus:V16QI (plus:V16QI
- (match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm"))
- (const_vector:V16QI [(const_int 1) (const_int 1)
- (const_int 1) (const_int 1)
- (const_int 1) (const_int 1)
- (const_int 1) (const_int 1)
- (const_int 1) (const_int 1)
- (const_int 1) (const_int 1)
- (const_int 1) (const_int 1)
- (const_int 1) (const_int 1)]))
- (const_int 1)))]
- "TARGET_SSE2"
- "pavgb\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_uavgv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (ashiftrt:V8HI
- (plus:V8HI (plus:V8HI
- (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm"))
- (const_vector:V8HI [(const_int 1) (const_int 1)
- (const_int 1) (const_int 1)
- (const_int 1) (const_int 1)
- (const_int 1) (const_int 1)]))
- (const_int 1)))]
- "TARGET_SSE2"
- "pavgw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-;; @@@ this isn't the right representation.
-(define_insn "sse2_psadbw"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (unspec:V2DI [(match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")]
- UNSPEC_PSADBW))]
- "TARGET_SSE2"
- "psadbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-
-;; MMX insert/extract/shuffle
-
-(define_insn "sse2_pinsrw"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (vec_merge:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (vec_duplicate:V8HI
- (truncate:HI
- (match_operand:SI 2 "nonimmediate_operand" "rm")))
- (match_operand:SI 3 "const_0_to_255_operand" "N")))]
- "TARGET_SSE2"
- "pinsrw\t{%3, %2, %0|%0, %2, %3}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_pextrw"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI
- (vec_select:HI (match_operand:V8HI 1 "register_operand" "x")
- (parallel
- [(match_operand:SI 2 "const_0_to_7_operand" "N")]))))]
- "TARGET_SSE2"
- "pextrw\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_pshufd"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "0")
- (match_operand:SI 2 "immediate_operand" "i")]
- UNSPEC_SHUFFLE))]
- "TARGET_SSE2"
- "pshufd\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_pshuflw"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "0")
- (match_operand:SI 2 "immediate_operand" "i")]
- UNSPEC_PSHUFLW))]
- "TARGET_SSE2"
- "pshuflw\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_pshufhw"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "0")
- (match_operand:SI 2 "immediate_operand" "i")]
- UNSPEC_PSHUFHW))]
- "TARGET_SSE2"
- "pshufhw\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-;; MMX mask-generating comparisons
-
-(define_insn "eqv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (eq:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pcmpeqb\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "TI")])
-
-(define_insn "eqv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (eq:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pcmpeqw\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "TI")])
-
-(define_insn "eqv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (eq:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pcmpeqd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "TI")])
-
-(define_insn "gtv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (gt:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pcmpgtb\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "TI")])
-
-(define_insn "gtv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (gt:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pcmpgtw\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "TI")])
-
-(define_insn "gtv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (gt:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pcmpgtd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecmp")
- (set_attr "mode" "TI")])
-
-
-;; MMX max/min insns
-
-(define_insn "umaxv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (umax:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pmaxub\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "smaxv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (smax:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pmaxsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "uminv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (umin:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pminub\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-(define_insn "sminv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (smin:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "pminsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
- (set_attr "mode" "TI")])
-
-
-;; MMX shifts
-
-(define_insn "ashrv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "xi")))]
- "TARGET_SSE2"
- "psraw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashrv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "xi")))]
- "TARGET_SSE2"
- "psrad\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "lshrv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "xi")))]
- "TARGET_SSE2"
- "psrlw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "lshrv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "xi")))]
- "TARGET_SSE2"
- "psrld\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "lshrv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "xi")))]
- "TARGET_SSE2"
- "psrlq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashlv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "xi")))]
- "TARGET_SSE2"
- "psllw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashlv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "xi")))]
- "TARGET_SSE2"
- "pslld\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashlv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "xi")))]
- "TARGET_SSE2"
- "psllq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashrv8hi3_ti"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
- "TARGET_SSE2"
- "psraw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashrv4si3_ti"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
- "TARGET_SSE2"
- "psrad\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "lshrv8hi3_ti"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
- "TARGET_SSE2"
- "psrlw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "lshrv4si3_ti"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
- "TARGET_SSE2"
- "psrld\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "lshrv2di3_ti"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0")
- (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
- "TARGET_SSE2"
- "psrlq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashlv8hi3_ti"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
- "TARGET_SSE2"
- "psllw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashlv4si3_ti"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
- "TARGET_SSE2"
- "pslld\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "ashlv2di3_ti"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0")
- (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
- "TARGET_SSE2"
- "psllq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-;; See logical MMX insns for the reason for the unspec. Strictly speaking
-;; we wouldn't need here it since we never generate TImode arithmetic.
-
-;; There has to be some kind of prize for the weirdest new instruction...
-(define_insn "sse2_ashlti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (unspec:TI
- [(ashift:TI (match_operand:TI 1 "register_operand" "0")
- (mult:SI (match_operand:SI 2 "immediate_operand" "i")
- (const_int 8)))] UNSPEC_NOP))]
- "TARGET_SSE2"
- "pslldq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_lshrti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (unspec:TI
- [(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
- (mult:SI (match_operand:SI 2 "immediate_operand" "i")
- (const_int 8)))] UNSPEC_NOP))]
- "TARGET_SSE2"
- "psrldq\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "mode" "TI")])
-
-;; SSE unpack
-
-(define_insn "sse2_unpckhpd"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_concat:V2DF
- (vec_select:DF (match_operand:V2DF 1 "register_operand" "0")
- (parallel [(const_int 1)]))
- (vec_select:DF (match_operand:V2DF 2 "register_operand" "x")
- (parallel [(const_int 1)]))))]
- "TARGET_SSE2"
- "unpckhpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-(define_insn "sse2_unpcklpd"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_concat:V2DF
- (vec_select:DF (match_operand:V2DF 1 "register_operand" "0")
- (parallel [(const_int 0)]))
- (vec_select:DF (match_operand:V2DF 2 "register_operand" "x")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE2"
- "unpcklpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-;; MMX pack/unpack insns.
-
-(define_insn "sse2_packsswb"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (vec_concat:V16QI
- (ss_truncate:V8QI (match_operand:V8HI 1 "register_operand" "0"))
- (ss_truncate:V8QI (match_operand:V8HI 2 "register_operand" "x"))))]
- "TARGET_SSE2"
- "packsswb\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_packssdw"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (vec_concat:V8HI
- (ss_truncate:V4HI (match_operand:V4SI 1 "register_operand" "0"))
- (ss_truncate:V4HI (match_operand:V4SI 2 "register_operand" "x"))))]
- "TARGET_SSE2"
- "packssdw\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_packuswb"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (vec_concat:V16QI
- (us_truncate:V8QI (match_operand:V8HI 1 "register_operand" "0"))
- (us_truncate:V8QI (match_operand:V8HI 2 "register_operand" "x"))))]
- "TARGET_SSE2"
- "packuswb\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_punpckhbw"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (vec_merge:V16QI
- (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (parallel [(const_int 8) (const_int 0)
- (const_int 9) (const_int 1)
- (const_int 10) (const_int 2)
- (const_int 11) (const_int 3)
- (const_int 12) (const_int 4)
- (const_int 13) (const_int 5)
- (const_int 14) (const_int 6)
- (const_int 15) (const_int 7)]))
- (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "x")
- (parallel [(const_int 0) (const_int 8)
- (const_int 1) (const_int 9)
- (const_int 2) (const_int 10)
- (const_int 3) (const_int 11)
- (const_int 4) (const_int 12)
- (const_int 5) (const_int 13)
- (const_int 6) (const_int 14)
- (const_int 7) (const_int 15)]))
- (const_int 21845)))]
- "TARGET_SSE2"
- "punpckhbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_punpckhwd"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (vec_merge:V8HI
- (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (parallel [(const_int 4) (const_int 0)
- (const_int 5) (const_int 1)
- (const_int 6) (const_int 2)
- (const_int 7) (const_int 3)]))
- (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "x")
- (parallel [(const_int 0) (const_int 4)
- (const_int 1) (const_int 5)
- (const_int 2) (const_int 6)
- (const_int 3) (const_int 7)]))
- (const_int 85)))]
- "TARGET_SSE2"
- "punpckhwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_punpckhdq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (vec_merge:V4SI
- (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (parallel [(const_int 2) (const_int 0)
- (const_int 3) (const_int 1)]))
- (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "x")
- (parallel [(const_int 0) (const_int 2)
- (const_int 1) (const_int 3)]))
- (const_int 5)))]
- "TARGET_SSE2"
- "punpckhdq\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_punpcklbw"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (vec_merge:V16QI
- (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "0")
- (parallel [(const_int 0) (const_int 8)
- (const_int 1) (const_int 9)
- (const_int 2) (const_int 10)
- (const_int 3) (const_int 11)
- (const_int 4) (const_int 12)
- (const_int 5) (const_int 13)
- (const_int 6) (const_int 14)
- (const_int 7) (const_int 15)]))
- (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "x")
- (parallel [(const_int 8) (const_int 0)
- (const_int 9) (const_int 1)
- (const_int 10) (const_int 2)
- (const_int 11) (const_int 3)
- (const_int 12) (const_int 4)
- (const_int 13) (const_int 5)
- (const_int 14) (const_int 6)
- (const_int 15) (const_int 7)]))
- (const_int 21845)))]
- "TARGET_SSE2"
- "punpcklbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_punpcklwd"
- [(set (match_operand:V8HI 0 "register_operand" "=x")
- (vec_merge:V8HI
- (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "0")
- (parallel [(const_int 0) (const_int 4)
- (const_int 1) (const_int 5)
- (const_int 2) (const_int 6)
- (const_int 3) (const_int 7)]))
- (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "x")
- (parallel [(const_int 4) (const_int 0)
- (const_int 5) (const_int 1)
- (const_int 6) (const_int 2)
- (const_int 7) (const_int 3)]))
- (const_int 85)))]
- "TARGET_SSE2"
- "punpcklwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_punpckldq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (vec_merge:V4SI
- (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "0")
- (parallel [(const_int 0) (const_int 2)
- (const_int 1) (const_int 3)]))
- (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "x")
- (parallel [(const_int 2) (const_int 0)
- (const_int 3) (const_int 1)]))
- (const_int 5)))]
- "TARGET_SSE2"
- "punpckldq\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_punpcklqdq"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (vec_merge:V2DI
- (vec_select:V2DI (match_operand:V2DI 2 "register_operand" "x")
- (parallel [(const_int 1)
- (const_int 0)]))
- (match_operand:V2DI 1 "register_operand" "0")
- (const_int 1)))]
- "TARGET_SSE2"
- "punpcklqdq\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_punpckhqdq"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (vec_merge:V2DI
- (match_operand:V2DI 1 "register_operand" "0")
- (vec_select:V2DI (match_operand:V2DI 2 "register_operand" "x")
- (parallel [(const_int 1)
- (const_int 0)]))
- (const_int 1)))]
- "TARGET_SSE2"
- "punpckhqdq\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-;; SSE2 moves
-
-(define_insn "sse2_movapd"
- [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
- (unspec:V2DF [(match_operand:V2DF 1 "nonimmediate_operand" "xm,x")]
- UNSPEC_MOVA))]
- "TARGET_SSE2
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "movapd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V2DF")])
-
-(define_insn "sse2_movupd"
- [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
- (unspec:V2DF [(match_operand:V2DF 1 "nonimmediate_operand" "xm,x")]
- UNSPEC_MOVU))]
- "TARGET_SSE2
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "movupd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-(define_insn "sse2_movdqa"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m")
- (unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "xm,x")]
- UNSPEC_MOVA))]
- "TARGET_SSE2
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "movdqa\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_movdqu"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m")
- (unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "xm,x")]
- UNSPEC_MOVU))]
- "TARGET_SSE2
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "movdqu\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_movdq2q"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,y")
- (vec_select:DI (match_operand:V2DI 1 "register_operand" "x,x")
- (parallel [(const_int 0)])))]
- "TARGET_SSE2 && !TARGET_64BIT"
- "@
- movq\t{%1, %0|%0, %1}
- movdq2q\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_movdq2q_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,y,r")
- (vec_select:DI (match_operand:V2DI 1 "register_operand" "x,x,x")
- (parallel [(const_int 0)])))]
- "TARGET_SSE2 && TARGET_64BIT"
- "@
- movq\t{%1, %0|%0, %1}
- movdq2q\t{%1, %0|%0, %1}
- movd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_movq2dq"
- [(set (match_operand:V2DI 0 "register_operand" "=x,?x")
- (vec_concat:V2DI (match_operand:DI 1 "nonimmediate_operand" "m,y")
- (const_int 0)))]
- "TARGET_SSE2 && !TARGET_64BIT"
- "@
- movq\t{%1, %0|%0, %1}
- movq2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt,ssemov")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_movq2dq_rex64"
- [(set (match_operand:V2DI 0 "register_operand" "=x,?x,?x")
- (vec_concat:V2DI (match_operand:DI 1 "nonimmediate_operand" "m,y,r")
- (const_int 0)))]
- "TARGET_SSE2 && TARGET_64BIT"
- "@
- movq\t{%1, %0|%0, %1}
- movq2dq\t{%1, %0|%0, %1}
- movd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt,ssemov,ssecvt")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_movq"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (vec_concat:V2DI (vec_select:DI
- (match_operand:V2DI 1 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)]))
- (const_int 0)))]
- "TARGET_SSE2"
- "movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_loadd"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (vec_merge:V4SI
- (vec_duplicate:V4SI (match_operand:SI 1 "nonimmediate_operand" "mr"))
- (const_vector:V4SI [(const_int 0)
- (const_int 0)
- (const_int 0)
- (const_int 0)])
- (const_int 1)))]
- "TARGET_SSE2"
- "movd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_stored"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=mr")
- (vec_select:SI
- (match_operand:V4SI 1 "register_operand" "x")
- (parallel [(const_int 0)])))]
- "TARGET_SSE2"
- "movd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_movhpd"
- [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
- (vec_merge:V2DF
- (match_operand:V2DF 1 "nonimmediate_operand" "0,0")
- (match_operand:V2DF 2 "nonimmediate_operand" "m,x")
- (const_int 2)))]
- "TARGET_SSE2 && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
- "movhpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
+ rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG);
+ ix86_compare_op0 = operands[0];
+ ix86_compare_op1 = operands[1];
+ ix86_compare_emitted = flags;
-(define_expand "sse2_loadsd"
- [(match_operand:V2DF 0 "register_operand" "")
- (match_operand:DF 1 "memory_operand" "")]
- "TARGET_SSE2"
-{
- emit_insn (gen_sse2_loadsd_1 (operands[0], operands[1],
- CONST0_RTX (V2DFmode)));
+#ifdef TARGET_THREAD_SSP_OFFSET
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_tls_protect_test_di (flags, operands[0],
+ GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+ else
+ emit_insn (gen_stack_tls_protect_test_si (flags, operands[0],
+ GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+#else
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1]));
+ else
+ emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1]));
+#endif
+ emit_jump_insn (gen_beq (operands[2]));
DONE;
})
-(define_insn "sse2_loadsd_1"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_merge:V2DF
- (vec_duplicate:V2DF (match_operand:DF 1 "memory_operand" "m"))
- (match_operand:V2DF 2 "const0_operand" "X")
- (const_int 1)))]
- "TARGET_SSE2"
- "movsd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "DF")])
-
-(define_insn "sse2_movsd"
- [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
- (vec_merge:V2DF
- (match_operand:V2DF 1 "nonimmediate_operand" "0,0,0")
- (match_operand:V2DF 2 "nonimmediate_operand" "x,m,x")
- (const_int 1)))]
- "TARGET_SSE2 && ix86_binary_operator_ok (UNKNOWN, V2DFmode, operands)"
- "@movsd\t{%2, %0|%0, %2}
- movlpd\t{%2, %0|%0, %2}
- movlpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "DF,V2DF,V2DF")])
-
-(define_insn "sse2_storesd"
- [(set (match_operand:DF 0 "memory_operand" "=m")
- (vec_select:DF
- (match_operand:V2DF 1 "register_operand" "x")
- (parallel [(const_int 0)])))]
- "TARGET_SSE2"
- "movsd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "DF")])
-
-(define_insn "sse2_shufpd"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")
- (match_operand:SI 3 "immediate_operand" "i")]
- UNSPEC_SHUFFLE))]
- "TARGET_SSE2"
- ;; @@@ check operand order for intel/nonintel syntax
- "shufpd\t{%3, %2, %0|%0, %2, %3}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V2DF")])
-
-(define_insn "sse2_clflush"
- [(unspec_volatile [(match_operand 0 "address_operand" "p")]
- UNSPECV_CLFLUSH)]
- "TARGET_SSE2"
- "clflush %0"
- [(set_attr "type" "sse")
- (set_attr "memory" "unknown")])
-
-(define_expand "sse2_mfence"
- [(set (match_dup 0)
- (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
- "TARGET_SSE2"
-{
- operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
- MEM_VOLATILE_P (operands[0]) = 1;
-})
-
-(define_insn "*mfence_insn"
- [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
- "TARGET_SSE2"
- "mfence"
- [(set_attr "type" "sse")
- (set_attr "memory" "unknown")])
+(define_insn "stack_protect_test_si"
+ [(set (match_operand:CCZ 0 "flags_reg_operand" "")
+ (unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
+ (match_operand:SI 2 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (clobber (match_scratch:SI 3 "=&r"))]
+ ""
+ "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%2, %3|%3, %2}"
+ [(set_attr "type" "multi")])
-(define_expand "sse2_lfence"
- [(set (match_dup 0)
- (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
- "TARGET_SSE2"
-{
- operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
- MEM_VOLATILE_P (operands[0]) = 1;
-})
+(define_insn "stack_protect_test_di"
+ [(set (match_operand:CCZ 0 "flags_reg_operand" "")
+ (unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
+ (match_operand:DI 2 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (clobber (match_scratch:DI 3 "=&r"))]
+ "TARGET_64BIT"
+ "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%2, %3|%3, %2}"
+ [(set_attr "type" "multi")])
-(define_insn "*lfence_insn"
- [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
- "TARGET_SSE2"
- "lfence"
- [(set_attr "type" "sse")
- (set_attr "memory" "unknown")])
-
-;; SSE3
-
-(define_insn "mwait"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "a")
- (match_operand:SI 1 "register_operand" "c")]
- UNSPECV_MWAIT)]
- "TARGET_SSE3"
- "mwait\t%0, %1"
- [(set_attr "length" "3")])
-
-(define_insn "monitor"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "a")
- (match_operand:SI 1 "register_operand" "c")
- (match_operand:SI 2 "register_operand" "d")]
- UNSPECV_MONITOR)]
- "TARGET_SSE3"
- "monitor\t%0, %1, %2"
- [(set_attr "length" "3")])
-
-;; SSE3 arithmetic
-
-(define_insn "addsubv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")]
- UNSPEC_ADDSUB))]
- "TARGET_SSE3"
- "addsubps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V4SF")])
-
-(define_insn "addsubv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")]
- UNSPEC_ADDSUB))]
- "TARGET_SSE3"
- "addsubpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V2DF")])
-
-(define_insn "haddv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")]
- UNSPEC_HADD))]
- "TARGET_SSE3"
- "haddps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V4SF")])
-
-(define_insn "haddv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")]
- UNSPEC_HADD))]
- "TARGET_SSE3"
- "haddpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V2DF")])
-
-(define_insn "hsubv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm")]
- UNSPEC_HSUB))]
- "TARGET_SSE3"
- "hsubps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V4SF")])
-
-(define_insn "hsubv2df3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0")
- (match_operand:V2DF 2 "nonimmediate_operand" "xm")]
- UNSPEC_HSUB))]
- "TARGET_SSE3"
- "hsubpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseadd")
- (set_attr "mode" "V2DF")])
-
-(define_insn "movshdup"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF
- [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_MOVSHDUP))]
- "TARGET_SSE3"
- "movshdup\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "V4SF")])
-
-(define_insn "movsldup"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF
- [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_MOVSLDUP))]
- "TARGET_SSE3"
- "movsldup\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "mode" "V4SF")])
-
-(define_insn "lddqu"
- [(set (match_operand:V16QI 0 "register_operand" "=x")
- (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "m")]
- UNSPEC_LDQQU))]
- "TARGET_SSE3"
- "lddqu\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "TI")])
+(define_insn "stack_tls_protect_test_si"
+ [(set (match_operand:CCZ 0 "flags_reg_operand" "")
+ (unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
+ (match_operand:SI 2 "const_int_operand" "i")]
+ UNSPEC_SP_TLS_TEST))
+ (clobber (match_scratch:SI 3 "=r"))]
+ ""
+ "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR %%gs:%P2}"
+ [(set_attr "type" "multi")])
-(define_insn "loadddup"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_duplicate:V2DF (match_operand:DF 1 "memory_operand" "m")))]
- "TARGET_SSE3"
- "movddup\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "DF")])
+(define_insn "stack_tls_protect_test_di"
+ [(set (match_operand:CCZ 0 "flags_reg_operand" "")
+ (unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
+ (match_operand:DI 2 "const_int_operand" "i")]
+ UNSPEC_SP_TLS_TEST))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_64BIT"
+ {
+ /* The kernel uses a different segment register for performance reasons; a
+ system call would not have to trash the userspace segment register,
+ which would be expensive */
+ if (ix86_cmodel != CM_KERNEL)
+ return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}";
+ else
+ return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}";
+ }
+ [(set_attr "type" "multi")])
-(define_insn "movddup"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_duplicate:V2DF
- (vec_select:DF (match_operand:V2DF 1 "register_operand" "x")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE3"
- "movddup\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "DF")])
+(include "sse.md")
+(include "mmx.md")
+(include "sync.md")
diff --git a/contrib/gcc/config/i386/x-cygwin b/contrib/gcc/config/i386/x-cygwin
new file mode 100644
index 0000000..cfd7758
--- /dev/null
+++ b/contrib/gcc/config/i386/x-cygwin
@@ -0,0 +1,4 @@
+host-cygwin.o : $(srcdir)/config/i386/host-cygwin.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) toplev.h diagnostic.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/host-cygwin.c
diff --git a/contrib/gcc/config/i386/x86-64.h b/contrib/gcc/config/i386/x86-64.h
index 6d1b811..f288208 100644
--- a/contrib/gcc/config/i386/x86-64.h
+++ b/contrib/gcc/config/i386/x86-64.h
@@ -1,5 +1,5 @@
/* OS independent definitions for AMD x86-64.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
Contributed by Bo Thorsen <bo@suse.de>.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* $FreeBSD$ */
@@ -51,22 +51,40 @@ Boston, MA 02111-1307, USA. */
#undef ASM_SPEC
#define ASM_SPEC "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} \
- %{Wa,*:%*} %{m32:--32}"
+ %{Wa,*:%*} %{m32:--32} %{m64:--64}"
+#undef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
- asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+ x86_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ x86_elf_aligned_common (FILE, NAME, SIZE, ALIGN);
/* This is used to align code labels according to Intel recommendations. */
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+ do { \
+ if ((LOG) != 0) { \
+ if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ } \
+ } while (0)
+#endif
+
/* i386 System V Release 4 uses DWARF debugging info.
x86-64 ABI specifies DWARF2. */
#define DWARF2_DEBUGGING_INFO 1
#define DWARF2_UNWIND_INFO 1
-/* Incorrectly autodetected in cross compilation. */
-#undef HAVE_AS_DWARF2_DEBUG_LINE
-#define HAVE_AS_DWARF2_DEBUG_LINE 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION x86_64_elf_select_section
+
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION x86_64_elf_unique_section
diff --git a/contrib/gcc/config/x-linux b/contrib/gcc/config/x-linux
index d14586b..e4aa040 100644
--- a/contrib/gcc/config/x-linux
+++ b/contrib/gcc/config/x-linux
@@ -1,4 +1,4 @@
host-linux.o : $(srcdir)/config/host-linux.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h hosthooks.h hosthooks-def.h
+ coretypes.h hosthooks.h hosthooks-def.h $(HOOKS_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/host-linux.c
diff --git a/contrib/gcc/configure b/contrib/gcc/configure
index 91f9326..a248d39 100755
--- a/contrib/gcc/configure
+++ b/contrib/gcc/configure
@@ -309,7 +309,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP GNATBIND ac_ct_GNATBIND strict1_warn warn_cflags WERROR nocommon_flag EGREP valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep SET_MAKE AWK LN LN_S RANLIB ac_ct_RANLIB INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON stage1_cflags COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LIBICONV_DEP manext objext extra_modes_file FORBUILD PACKAGE VERSION USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS CROSS ALL SYSTEM_HEADER_DIR inhibit_libc BUILD_PREFIX BUILD_PREFIX_1 CC_FOR_BUILD BUILD_CFLAGS STMP_FIXINC STMP_FIXPROTO libgcc_visibility gthread_flags GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir objdir subdirs srcdir all_boot_languages all_compilers all_gtfiles all_gtfiles_files_langs all_gtfiles_files_files all_lang_makefrags all_lang_makefiles all_languages all_stagestuff build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines check_languages cc_set_by_configure quoted_cc_set_by_configure cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir libstdcxx_incdir gcc_version gcc_version_full gcc_version_trigger host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file stage_prefix_set_by_configure quoted_stage_prefix_set_by_configure symbolic_link thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines target_noncanonical c_target_objs cxx_target_objs target_cpu_default set_gcc_lib_path LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP strict1_warn cxx_compat_warn warn_cflags WERROR nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR stage1_cflags COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT host_cc_for_libada CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS STMP_FIXINC STMP_FIXPROTO collect2 gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir objdir subdirs srcdir all_boot_languages all_compilers all_gtfiles all_gtfiles_files_langs all_gtfiles_files_files all_lang_makefrags all_lang_makefiles all_languages all_selected_languages all_stagestuff build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines check_languages cc_set_by_configure quoted_cc_set_by_configure cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file stage_prefix_set_by_configure quoted_stage_prefix_set_by_configure thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs target_cpu_default GMPLIBS GMPINC LIBOBJS LTLIBOBJS'
ac_subst_files='language_hooks'
# Initialize some variables set by options.
@@ -770,6 +770,14 @@ ac_env_CPP_set=${CPP+set}
ac_env_CPP_value=$CPP
ac_cv_env_CPP_set=${CPP+set}
ac_cv_env_CPP_value=$CPP
+ac_env_GMPLIBS_set=${GMPLIBS+set}
+ac_env_GMPLIBS_value=$GMPLIBS
+ac_cv_env_GMPLIBS_set=${GMPLIBS+set}
+ac_cv_env_GMPLIBS_value=$GMPLIBS
+ac_env_GMPINC_set=${GMPINC+set}
+ac_env_GMPINC_value=$GMPINC
+ac_cv_env_GMPINC_set=${GMPINC+set}
+ac_cv_env_GMPINC_value=$GMPINC
#
# Report the --help message.
@@ -854,14 +862,17 @@ Optional Features:
put copies of generated files in source dir
intended for creating source tarballs for users
without texinfo bison or flex.
+ --enable-werror-always enable -Werror always
--enable-werror enable -Werror in bootstrap stage2 and later
--enable-checking=LIST
enable expensive run-time checks. With LIST,
enable only specific categories of checks.
- Categories are: misc,tree,rtl,rtlflag,gc,gcac,fold;
- default is no checking
+ Categories are: yes,no,all,none,release.
+ Flags are: assert,fold,gc,gcac,misc,
+ rtlflag,rtl,runtime,tree,valgrind.
+ --enable-mapped-location location_t is fileline integer cookie
--enable-coverage=LEVEL
- enable compiler\'s code coverage collection.
+ enable compiler's code coverage collection.
Use to measure compiler performance and locate
unused parts of the compiler. With LEVEL, specify
optimization. Values are opt, noopt,
@@ -869,15 +880,21 @@ Optional Features:
--enable-gather-detailed-mem-stats enable detailed memory allocation stats gathering
--enable-multilib enable library support for multiple ABIs
--enable-__cxa_atexit enable __cxa_atexit for C++
+ --enable-decimal-float enable decimal float extension to C
--enable-threads enable thread usage for target GCC
--enable-threads=LIB use LIB thread package for target GCC
+ --enable-tls enable or disable generation of tls code
+ overriding the assembler check for tls support
--enable-objc-gc enable the use of Boehm's garbage collector with
the GNU Objective-C runtime
--disable-shared don't provide a shared libgcc
--enable-intermodule build the compiler in one step
+ --enable-languages=LIST specify which front-ends to build
+ --disable-rpath do not hardcode runtime library paths
--enable-initfini-array use .init_array/.fini_array sections
--enable-sjlj-exceptions
arrange to use setjmp/longjmp exception handling
+ --enable-secureplt enable -msecure-plt by default for PowerPC
--disable-win32-registry
disable lookup of installation paths in the
Registry on Windows hosts
@@ -895,6 +912,7 @@ Optional Features:
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-build-libsubdir=DIR Directory where to find libraries for build system
--with-local-prefix=DIR specifies directory to put local include
--with-gxx-include-dir=DIR
specifies directory to put g++ header files
@@ -903,17 +921,26 @@ Optional Packages:
(relative to PREFIX) as well as PREFIX/bin
--with-gnu-ld arrange to work with GNU ld.
--with-ld arrange to use the specified ld (full pathname)
+ --with-demangler-in-ld try to use demangler in GNU ld.
--with-gnu-as arrange to work with GNU as
--with-as arrange to use the specified as (full pathname)
--with-stabs arrange to use stabs instead of host debug format
--with-dwarf2 force the default debug format to be DWARF 2
+ --with-build-sysroot=sysroot
+ use sysroot as the system root during the build
--with-sysroot=DIR Search for usr/lib, usr/include, et al, within DIR.
- --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib
+ --with-gnu-ld assume the C compiler uses GNU ld default=no
+ --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
+ --without-libiconv-prefix don't search for libiconv in includedir and libdir
--with-system-libunwind use installed libunwind
- --with-gc={simple,page,zone} choose the garbage collection mechanism to use
+ --with-long-double-128 Use 128-bit long double by default.
+ --with-gc={page,zone} choose the garbage collection mechanism to use
with the compiler
--with-system-zlib use installed libz
- --with-slibdir=DIR shared libraries in DIR LIBDIR
+ --with-slibdir=DIR shared libraries in DIR [LIBDIR]
+ --with-datarootdir=DIR Use DIR as the data root [PREFIX/share]
+ --with-docdir=DIR Install documentation in DIR [DATAROOTDIR]
+ --with-htmldir=DIR html documentation in in DIR [DOCDIR]
Some influential environment variables:
CC C compiler command
@@ -923,6 +950,8 @@ Some influential environment variables:
CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
headers in a nonstandard directory <include dir>
CPP C preprocessor
+ GMPLIBS How to link GMP
+ GMPINC How to find GMP include files
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1366,6 +1395,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers auto-host.h:config.in"
+gcc_version=`cat $srcdir/BASE-VER`
+
# Determine the host, build, and target systems
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
@@ -1492,11 +1523,36 @@ esac
esac
+
+
# Determine the target- and build-specific subdirectories
- # Prefix 'build-' so this never conflicts with target_subdir.
+
+# post-stage1 host modules use a different CC_FOR_BUILD so, in order to
+# have matching libraries, they should use host libraries: Makefile.tpl
+# arranges to pass --with-build-libsubdir=$(HOST_SUBDIR).
+# However, they still use the build modules, because the corresponding
+# host modules (e.g. bison) are only built for the host when bootstrap
+# finishes. So:
+# - build_subdir is where we find build modules, and never changes.
+# - build_libsubdir is where we find build libraries, and can be overridden.
+
+# Prefix 'build-' so this never conflicts with target_subdir.
build_subdir="build-${build_noncanonical}"
-# Not really a subdirectory, but here for completeness.
-host_subdir=.
+
+# Check whether --with-build-libsubdir or --without-build-libsubdir was given.
+if test "${with_build_libsubdir+set}" = set; then
+ withval="$with_build_libsubdir"
+ build_libsubdir="$withval"
+else
+ build_libsubdir="$build_subdir"
+fi;
+# --srcdir=. covers the toplevel, while "test -d" covers the subdirectories
+if ( test $srcdir = . && test -d gcc ) \
+ || test -d $srcdir/../host-${host_noncanonical}; then
+ host_subdir="host-${host_noncanonical}"
+else
+ host_subdir=.
+fi
# No prefix.
target_subdir=${target_noncanonical}
@@ -1621,12 +1677,16 @@ no) ;;
esac
fi;
+# This logic must match libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.
if test x${gcc_gxx_include_dir} = x; then
if test x${enable_version_specific_runtime_libs} = xyes; then
gcc_gxx_include_dir='${libsubdir}/include/c++'
else
- topsrcdir=${srcdir}/.. . ${srcdir}/../config.if
- gcc_gxx_include_dir="\$(libsubdir)/\$(unlibsubdir)/..\`echo \$(exec_prefix) | sed -e 's|^\$(prefix)||' -e 's|/[^/]*|/..|g'\`/include/"${libstdcxx_incdir}
+ libstdcxx_incdir='include/c++/$(version)'
+ if test x$host != x$target; then
+ libstdcxx_incdir="$target_alias/$libstdcxx_incdir"
+ fi
+ gcc_gxx_include_dir="\$(libsubdir)/\$(unlibsubdir)/..\`echo \$(exec_prefix) | sed -e 's|^\$(prefix)||' -e 's|/[^/]*|/..|g'\`/$libstdcxx_incdir"
fi
fi
@@ -1692,8 +1752,9 @@ if test "${with_ld+set}" = set; then
fi;
if test x"${DEFAULT_LINKER+set}" = x"set"; then
if test ! -x "$DEFAULT_LINKER"; then
- { echo "$as_me:$LINENO: WARNING: cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER" >&5
-echo "$as_me: WARNING: cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER" >&2;}
+ { { echo "$as_me:$LINENO: error: cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER" >&5
+echo "$as_me: error: cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER" >&2;}
+ { (exit 1); exit 1; }; }
elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
gnu_ld_flag=yes
fi
@@ -1719,6 +1780,16 @@ else
echo "${ECHO_T}no" >&6
fi
+# With demangler in GNU ld
+
+# Check whether --with-demangler-in-ld or --without-demangler-in-ld was given.
+if test "${with_demangler_in_ld+set}" = set; then
+ withval="$with_demangler_in_ld"
+ demangler_in_ld="$with_demangler_in_ld"
+else
+ demangler_in_ld=no
+fi;
+
# ----------------------
# Find default assembler
# ----------------------
@@ -1741,8 +1812,9 @@ if test "${with_as+set}" = set; then
fi;
if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
if test ! -x "$DEFAULT_ASSEMBLER"; then
- { echo "$as_me:$LINENO: WARNING: cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER" >&5
-echo "$as_me: WARNING: cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER" >&2;}
+ { { echo "$as_me:$LINENO: error: cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER" >&5
+echo "$as_me: error: cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER" >&2;}
+ { (exit 1); exit 1; }; }
elif $DEFAULT_ASSEMBLER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
gas_flag=yes
fi
@@ -2802,6 +2874,22 @@ _ACEOF
fi
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+
# autoconf is lame and doesn't give us any substitution variable for this.
if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = no"; then
NO_MINUS_C_MINUS_O=yes
@@ -2811,68 +2899,18 @@ fi
+# Remove the -O2: for historical reasons, unless bootstrapping we prefer
+# optimizations to be activated explicitly by the toplevel.
+case "$CC" in
+ */prev-gcc/xgcc*) ;;
+ *) CFLAGS=`echo $CFLAGS | sed "s/-O[s0-9]* *//" ` ;;
+esac
+
+
# -------------------------
# Check C compiler features
# -------------------------
-
-echo "$as_me:$LINENO: checking whether ${CC-cc} accepts -Wno-long-long" >&5
-echo $ECHO_N "checking whether ${CC-cc} accepts -Wno-long-long... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_no_long_long+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- save_CFLAGS="$CFLAGS"
-CFLAGS="-Wno-long-long"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_no_long_long=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cc_no_long_long=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-CFLAGS="$save_CFLAGS"
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_no_long_long" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_no_long_long" >&6
-
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3107,6 +3145,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
echo "$as_me:$LINENO: checking for inline" >&5
echo $ECHO_N "checking for inline... $ECHO_C" >&6
if test "${ac_cv_c_inline+set}" = set; then
@@ -3179,9 +3218,26 @@ _ACEOF
esac
-echo "$as_me:$LINENO: checking for long long int" >&5
-echo $ECHO_N "checking for long long int... $ECHO_C" >&6
-if test "${ac_cv_c_long_long+set}" = set; then
+# sizeof(char) is 1 by definition.
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
@@ -3190,11 +3246,15 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
int
main ()
{
-long long int i;
+
;
return 0;
}
@@ -3221,28 +3281,61 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_c_long_long=yes
+ ac_cv_header_stdc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-ac_cv_c_long_long=no
+ac_cv_header_stdc=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
fi
-echo "$as_me:$LINENO: result: $ac_cv_c_long_long" >&5
-echo "${ECHO_T}$ac_cv_c_long_long" >&6
- if test $ac_cv_c_long_long = yes; then
+rm -f conftest*
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LONG_LONG 1
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
- fi
-echo "$as_me:$LINENO: checking for __int64" >&5
-echo $ECHO_N "checking for __int64... $ECHO_C" >&6
-if test "${ac_cv_c___int64+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
@@ -3250,15 +3343,93 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int
main ()
{
-__int64 i;
- ;
- return 0;
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
}
_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>conftest.er1
@@ -3281,28 +3452,30 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_c___int64=yes
+ eval "$as_ac_Header=yes"
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-ac_cv_c___int64=no
+eval "$as_ac_Header=no"
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_c___int64" >&5
-echo "${ECHO_T}$ac_cv_c___int64" >&6
- if test $ac_cv_c___int64 = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE___INT64 1
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
- fi
+fi
-echo "$as_me:$LINENO: checking for built-in _Bool" >&5
-echo $ECHO_N "checking for built-in _Bool... $ECHO_C" >&6
-if test "${gcc_cv_c__bool+set}" = set; then
+done
+
+
+echo "$as_me:$LINENO: checking for void *" >&5
+echo $ECHO_N "checking for void *... $ECHO_C" >&6
+if test "${ac_cv_type_void_p+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
@@ -3311,11 +3484,14 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-
+$ac_includes_default
int
main ()
{
-_Bool foo;
+if ((void * *) 0)
+ return 0;
+if (sizeof (void *))
+ return 0;
;
return 0;
}
@@ -3342,48 +3518,182 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- gcc_cv_c__bool=yes
+ ac_cv_type_void_p=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-gcc_cv_c__bool=no
+ac_cv_type_void_p=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-echo "$as_me:$LINENO: result: $gcc_cv_c__bool" >&5
-echo "${ECHO_T}$gcc_cv_c__bool" >&6
-if test $gcc_cv_c__bool = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE__BOOL 1
-_ACEOF
-
fi
+echo "$as_me:$LINENO: result: $ac_cv_type_void_p" >&5
+echo "${ECHO_T}$ac_cv_type_void_p" >&6
-
-# sizeof(char) is 1 by definition.
echo "$as_me:$LINENO: checking size of void *" >&5
echo $ECHO_N "checking size of void *... $ECHO_C" >&6
if test "${ac_cv_sizeof_void_p+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
- cat >conftest.$ac_ext <<_ACEOF
+ if test "$ac_cv_type_void_p" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include "confdefs.h"
-#include <sys/types.h>
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
int
main ()
{
-switch (0) case 0: case (sizeof (void *) == $ac_size):;
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= $ac_mid)];
+test_array [0] = 0
+
;
return 0;
}
@@ -3410,51 +3720,394 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_sizeof_void_p=$ac_size
+ ac_lo=$ac_mid; break
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test x$ac_cv_sizeof_void_p != x ; then break; fi
-done
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)];
+test_array [0] = 0
-if test x$ac_cv_sizeof_void_p = x ; then
- { { echo "$as_me:$LINENO: error: cannot determine a size for void *" >&5
-echo "$as_me: error: cannot determine a size for void *" >&2;}
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_void_p=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (void *), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (void *)); }
+unsigned long ulongval () { return (long) (sizeof (void *)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (void *))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (void *))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (void *))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_void_p=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (void *), 77
+See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; }
fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_void_p=0
+fi
+fi
echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5
echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6
-
cat >>confdefs.h <<_ACEOF
#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
_ACEOF
+echo "$as_me:$LINENO: checking for short" >&5
+echo $ECHO_N "checking for short... $ECHO_C" >&6
+if test "${ac_cv_type_short+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((short *) 0)
+ return 0;
+if (sizeof (short))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_short=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_short=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_short" >&5
+echo "${ECHO_T}$ac_cv_type_short" >&6
+
echo "$as_me:$LINENO: checking size of short" >&5
echo $ECHO_N "checking size of short... $ECHO_C" >&6
if test "${ac_cv_sizeof_short+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
- cat >conftest.$ac_ext <<_ACEOF
+ if test "$ac_cv_type_short" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include "confdefs.h"
-#include <sys/types.h>
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) >= 0)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
int
main ()
{
-switch (0) case 0: case (sizeof (short) == $ac_size):;
+static int test_array [1 - 2 * !(((long) (sizeof (short))) >= $ac_mid)];
+test_array [0] = 0
+
;
return 0;
}
@@ -3481,51 +4134,296 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_sizeof_short=$ac_size
+ ac_lo=$ac_mid; break
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test x$ac_cv_sizeof_short != x ; then break; fi
-done
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_short=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (short), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (short), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (short)); }
+unsigned long ulongval () { return (long) (sizeof (short)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (short))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (short))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (short))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_short=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-if test x$ac_cv_sizeof_short = x ; then
- { { echo "$as_me:$LINENO: error: cannot determine a size for short" >&5
-echo "$as_me: error: cannot determine a size for short" >&2;}
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (short), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (short), 77
+See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; }
fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_short=0
+fi
+fi
echo "$as_me:$LINENO: result: $ac_cv_sizeof_short" >&5
echo "${ECHO_T}$ac_cv_sizeof_short" >&6
-
cat >>confdefs.h <<_ACEOF
#define SIZEOF_SHORT $ac_cv_sizeof_short
_ACEOF
+echo "$as_me:$LINENO: checking for int" >&5
+echo $ECHO_N "checking for int... $ECHO_C" >&6
+if test "${ac_cv_type_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((int *) 0)
+ return 0;
+if (sizeof (int))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_int=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_int=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
+echo "${ECHO_T}$ac_cv_type_int" >&6
+
echo "$as_me:$LINENO: checking size of int" >&5
echo $ECHO_N "checking size of int... $ECHO_C" >&6
if test "${ac_cv_sizeof_int+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
- cat >conftest.$ac_ext <<_ACEOF
+ if test "$ac_cv_type_int" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include "confdefs.h"
-#include <sys/types.h>
-
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
int
main ()
{
-switch (0) case 0: case (sizeof (int) == $ac_size):;
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
;
return 0;
}
@@ -3552,51 +4450,143 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_sizeof_int=$ac_size
+ ac_hi=$ac_mid; break
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test x$ac_cv_sizeof_int != x ; then break; fi
-done
-
-fi
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-if test x$ac_cv_sizeof_int = x ; then
- { { echo "$as_me:$LINENO: error: cannot determine a size for int" >&5
-echo "$as_me: error: cannot determine a size for int" >&2;}
- { (exit 1); exit 1; }; }
-fi
-echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
-echo "${ECHO_T}$ac_cv_sizeof_int" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)];
+test_array [0] = 0
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-echo "$as_me:$LINENO: checking size of long" >&5
-echo $ECHO_N "checking size of long... $ECHO_C" >&6
-if test "${ac_cv_sizeof_long+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
else
- for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include "confdefs.h"
-#include <sys/types.h>
-
-
+$ac_includes_default
int
main ()
{
-switch (0) case 0: case (sizeof (long) == $ac_size):;
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
;
return 0;
}
@@ -3623,52 +4613,127 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_sizeof_long=$ac_size
+ ac_hi=$ac_mid
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo=`expr '(' $ac_mid ')' + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test x$ac_cv_sizeof_long != x ; then break; fi
done
+case $ac_lo in
+?*) ac_cv_sizeof_int=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (int)); }
+unsigned long ulongval () { return (long) (sizeof (int)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
-fi
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (int))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (int))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (int))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_int=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-if test x$ac_cv_sizeof_long = x ; then
- { { echo "$as_me:$LINENO: error: cannot determine a size for long" >&5
-echo "$as_me: error: cannot determine a size for long" >&2;}
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; }
fi
-echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
-echo "${ECHO_T}$ac_cv_sizeof_long" >&6
-
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_int=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6
cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
+#define SIZEOF_INT $ac_cv_sizeof_int
_ACEOF
-if test $ac_cv_c_long_long = yes; then
- echo "$as_me:$LINENO: checking size of long long" >&5
-echo $ECHO_N "checking size of long long... $ECHO_C" >&6
-if test "${ac_cv_sizeof_long_long+set}" = set; then
+echo "$as_me:$LINENO: checking for long" >&5
+echo $ECHO_N "checking for long... $ECHO_C" >&6
+if test "${ac_cv_type_long+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include "confdefs.h"
-#include <sys/types.h>
-
-
+$ac_includes_default
int
main ()
{
-switch (0) case 0: case (sizeof (long long) == $ac_size):;
+if ((long *) 0)
+ return 0;
+if (sizeof (long))
+ return 0;
;
return 0;
}
@@ -3695,53 +4760,182 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_sizeof_long_long=$ac_size
+ ac_cv_type_long=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_type_long=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test x$ac_cv_sizeof_long_long != x ; then break; fi
-done
-
fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5
+echo "${ECHO_T}$ac_cv_type_long" >&6
-if test x$ac_cv_sizeof_long_long = x ; then
- { { echo "$as_me:$LINENO: error: cannot determine a size for long long" >&5
-echo "$as_me: error: cannot determine a size for long long" >&2;}
- { (exit 1); exit 1; }; }
-fi
-echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5
-echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6
+echo "$as_me:$LINENO: checking size of long" >&5
+echo $ECHO_N "checking size of long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_long" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)];
+test_array [0] = 0
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+ ;
+ return 0;
+}
_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
fi
-if test $ac_cv_c___int64 = yes; then
- echo "$as_me:$LINENO: checking size of __int64" >&5
-echo $ECHO_N "checking size of __int64... $ECHO_C" >&6
-if test "${ac_cv_sizeof___int64+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
else
- for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
- cat >conftest.$ac_ext <<_ACEOF
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include "confdefs.h"
-#include <sys/types.h>
-
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
int
main ()
{
-switch (0) case 0: case (sizeof (__int64) == $ac_size):;
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)];
+test_array [0] = 0
+
;
return 0;
}
@@ -3768,319 +4962,835 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_sizeof___int64=$ac_size
+ ac_lo=$ac_mid; break
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- if test x$ac_cv_sizeof___int64 != x ; then break; fi
-done
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo= ac_hi=
fi
-
-if test x$ac_cv_sizeof___int64 = x ; then
- { { echo "$as_me:$LINENO: error: cannot determine a size for __int64" >&5
-echo "$as_me: error: cannot determine a size for __int64" >&2;}
- { (exit 1); exit 1; }; }
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_sizeof___int64" >&5
-echo "${ECHO_T}$ac_cv_sizeof___int64" >&6
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF___INT64 $ac_cv_sizeof___int64
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo=`expr '(' $ac_mid ')' + 1`
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (long)); }
+unsigned long ulongval () { return (long) (sizeof (long)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
-# -----------------
-# Find Ada compiler
-# -----------------
-
-# See if GNAT has been installed
-
-
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (long))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (long))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (long))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gnatbind", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gnatbind; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_GNATBIND+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$GNATBIND"; then
- ac_cv_prog_GNATBIND="$GNATBIND" # Let the user override the test.
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long=`cat conftest.val`
else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_GNATBIND="${ac_tool_prefix}gnatbind"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
-GNATBIND=$ac_cv_prog_GNATBIND
-if test -n "$GNATBIND"; then
- echo "$as_me:$LINENO: result: $GNATBIND" >&5
-echo "${ECHO_T}$GNATBIND" >&6
+rm -f conftest.val
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ ac_cv_sizeof_long=0
fi
-
fi
-if test -z "$ac_cv_prog_GNATBIND"; then
- ac_ct_GNATBIND=$GNATBIND
- # Extract the first word of "gnatbind", so it can be a program name with args.
-set dummy gnatbind; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_GNATBIND+set}" = set; then
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for long long" >&5
+echo $ECHO_N "checking for long long... $ECHO_C" >&6
+if test "${ac_cv_type_long_long+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- if test -n "$ac_ct_GNATBIND"; then
- ac_cv_prog_ac_ct_GNATBIND="$ac_ct_GNATBIND" # Let the user override the test.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((long long *) 0)
+ return 0;
+if (sizeof (long long))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_long_long=yes
else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_GNATBIND="gnatbind"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
- test -z "$ac_cv_prog_ac_ct_GNATBIND" && ac_cv_prog_ac_ct_GNATBIND="no"
+ac_cv_type_long_long=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-ac_ct_GNATBIND=$ac_cv_prog_ac_ct_GNATBIND
-if test -n "$ac_ct_GNATBIND"; then
- echo "$as_me:$LINENO: result: $ac_ct_GNATBIND" >&5
-echo "${ECHO_T}$ac_ct_GNATBIND" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5
+echo "${ECHO_T}$ac_cv_type_long_long" >&6
+if test $ac_cv_type_long_long = yes; then
- GNATBIND=$ac_ct_GNATBIND
-else
- GNATBIND="$ac_cv_prog_GNATBIND"
-fi
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LONG_LONG 1
+_ACEOF
-echo "$as_me:$LINENO: checking whether compiler driver understands Ada" >&5
-echo $ECHO_N "checking whether compiler driver understands Ada... $ECHO_C" >&6
-if test "${gcc_cv_cc_supports_ada+set}" = set; then
+echo "$as_me:$LINENO: checking for long long" >&5
+echo $ECHO_N "checking for long long... $ECHO_C" >&6
+if test "${ac_cv_type_long_long+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat >conftest.adb <<EOF
-procedure conftest is begin null; end conftest;
-EOF
-gcc_cv_cc_supports_ada=no
-# There is a bug in old released versions of GCC which causes the
-# driver to exit successfully when the appropriate language module
-# has not been installed. This is fixed in 2.95.4, 3.0.2, and 3.1.
-# Therefore we must check for the error message as well as an
-# unsuccessful exit.
-# Other compilers, like HP Tru64 UNIX cc, exit successfully when
-# given a .adb file, but produce no object file. So we must check
-# if an object file was really produced to guard against this.
-errors=`(${CC} -c conftest.adb) 2>&1 || echo failure`
-if test x"$errors" = x && test -f conftest.$ac_objext; then
- gcc_cv_cc_supports_ada=yes
- break
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((long long *) 0)
+ return 0;
+if (sizeof (long long))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_long_long=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_long_long=no
fi
-rm -f conftest.*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $gcc_cv_cc_supports_ada" >&5
-echo "${ECHO_T}$gcc_cv_cc_supports_ada" >&6
+echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5
+echo "${ECHO_T}$ac_cv_type_long_long" >&6
-if test x$GNATBIND != xno && test x$gcc_cv_cc_supports_ada != xno; then
- have_gnat=yes
+echo "$as_me:$LINENO: checking size of long long" >&5
+echo $ECHO_N "checking size of long long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- have_gnat=no
-fi
+ if test "$ac_cv_type_long_long" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= 0)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)];
+test_array [0] = 0
-# ---------------------
-# Warnings and checking
-# ---------------------
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-strict1_warn=
-if test $ac_cv_prog_cc_no_long_long = yes ; then
- strict1_warn="-pedantic -Wno-long-long"
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) < 0)];
+test_array [0] = 0
-# If the native compiler is GCC, we can enable warnings even in stage1.
-# That's useful for people building cross-compilers, or just running a
-# quick `make'.
-warn_cflags=
-if test "x$GCC" = "xyes"; then
- warn_cflags='$(GCC_WARN_CFLAGS)'
-fi
-
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) >= $ac_mid)];
+test_array [0] = 0
-# Enable -Werror in bootstrap stage2 and later.
-# Change the default to "no" on release branches.
-# Check whether --enable-werror or --disable-werror was given.
-if test "${enable_werror+set}" = set; then
- enableval="$enable_werror"
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
else
- enable_werror=no
-fi;
-if test x$enable_werror = xyes ; then
- WERROR=-Werror
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long long))) <= $ac_mid)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-# Enable expensive internal checks
-# Check whether --enable-checking or --disable-checking was given.
-if test "${enable_checking+set}" = set; then
- enableval="$enable_checking"
- ac_checking=
-ac_tree_checking=
-ac_rtl_checking=
-ac_rtlflag_checking=
-ac_gc_checking=
-ac_gc_always_collect=
-ac_fold_checking=
-case "${enableval}" in
-yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;
- ac_rtlflag_checking=1 ;;
-no) ;;
-*) IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="$IFS,"
- set fnord $enableval; shift
- IFS="$ac_save_IFS"
- for check
- do
- case $check in
- misc) ac_checking=1 ;;
- tree) ac_tree_checking=1 ;;
- rtlflag) ac_rtlflag_checking=1 ;;
- rtl) ac_rtl_checking=1 ;;
- gc) ac_gc_checking=1 ;;
- gcac) ac_gc_always_collect=1 ;;
- fold) ac_fold_checking=1 ;;
- valgrind) ac_checking_valgrind=1 ;;
- *) { { echo "$as_me:$LINENO: error: unknown check category $check" >&5
-echo "$as_me: error: unknown check category $check" >&2;}
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_long=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long long), 77
+See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; } ;;
- esac
- done
- ;;
esac
-
else
- # By default, disable all checks for release versions of GCC.
-ac_checking=; ac_tree_checking=; ac_gc_checking=; ac_rtlflag_checking=;
-fi;
-nocommon_flag=""
-if test x$ac_checking != x ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_CHECKING 1
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (long long)); }
+unsigned long ulongval () { return (long) (sizeof (long long)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
- nocommon_flag=-fno-common
-fi
-
-if test x$ac_tree_checking != x ; then
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (long long))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (long long))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (long long))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_TREE_CHECKING 1
+ ;
+ return 0;
+}
_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long_long=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long long), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
-if test x$ac_rtl_checking != x ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_RTL_CHECKING 1
-_ACEOF
-
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-if test x$ac_rtlflag_checking != x ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_RTL_FLAG_CHECKING 1
-_ACEOF
-
fi
-if test x$ac_gc_checking != x ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_GC_CHECKING 1
-_ACEOF
-
+rm -f conftest.val
+else
+ ac_cv_sizeof_long_long=0
fi
-if test x$ac_gc_always_collect != x ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_GC_ALWAYS_COLLECT 1
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
_ACEOF
+
fi
-if test x$ac_fold_checking != x ; then
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_FOLD_CHECKING 1
+echo "$as_me:$LINENO: checking for __int64" >&5
+echo $ECHO_N "checking for __int64... $ECHO_C" >&6
+if test "${ac_cv_type___int64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((__int64 *) 0)
+ return 0;
+if (sizeof (__int64))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type___int64=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_type___int64=no
fi
-valgrind_path_defines=
-valgrind_command=
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type___int64" >&5
+echo "${ECHO_T}$ac_cv_type___int64" >&6
+if test $ac_cv_type___int64 = yes; then
+cat >>confdefs.h <<_ACEOF
+#define HAVE___INT64 1
+_ACEOF
-echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6
-if test "${ac_cv_prog_egrep+set}" = set; then
+echo "$as_me:$LINENO: checking for __int64" >&5
+echo $ECHO_N "checking for __int64... $ECHO_C" >&6
+if test "${ac_cv_type___int64+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- if echo a | (grep -E '(a|b)') >/dev/null 2>&1
- then ac_cv_prog_egrep='grep -E'
- else ac_cv_prog_egrep='egrep'
- fi
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
-echo "${ECHO_T}$ac_cv_prog_egrep" >&6
- EGREP=$ac_cv_prog_egrep
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((__int64 *) 0)
+ return 0;
+if (sizeof (__int64))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type___int64=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_type___int64=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type___int64" >&5
+echo "${ECHO_T}$ac_cv_type___int64" >&6
-echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
-if test "${ac_cv_header_stdc+set}" = set; then
+echo "$as_me:$LINENO: checking size of __int64" >&5
+echo $ECHO_N "checking size of __int64... $ECHO_C" >&6
+if test "${ac_cv_sizeof___int64+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat >conftest.$ac_ext <<_ACEOF
+ if test "$ac_cv_type___int64" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (__int64))) >= 0)];
+test_array [0] = 0
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
int
main ()
{
+static int test_array [1 - 2 * !(((long) (sizeof (__int64))) <= $ac_mid)];
+test_array [0] = 0
;
return 0;
@@ -4108,61 +5818,193 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_header_stdc=yes
+ ac_hi=$ac_mid; break
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-ac_cv_header_stdc=no
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
+cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <string.h>
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (__int64))) < 0)];
+test_array [0] = 0
+ ;
+ return 0;
+}
_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then
- :
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (__int64))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <stdlib.h>
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (__int64))) <= $ac_mid)];
+test_array [0] = 0
+ ;
+ return 0;
+}
_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then
- :
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_lo=`expr '(' $ac_mid ')' + 1`
fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof___int64=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (__int64), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (__int64), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
if test "$cross_compiling" = yes; then
- :
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
@@ -4170,28 +6012,36 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <ctype.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+$ac_includes_default
+long longval () { return (long) (sizeof (__int64)); }
+unsigned long ulongval () { return (long) (sizeof (__int64)); }
+#include <stdio.h>
+#include <stdlib.h>
int
main ()
{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- exit(2);
- exit (0);
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (__int64))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (__int64))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (__int64))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
}
_ACEOF
rm -f conftest$ac_exeext
@@ -4205,57 +6055,223 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- :
+ ac_cv_sizeof___int64=`cat conftest.val`
else
echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
( exit $ac_status )
-ac_cv_header_stdc=no
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (__int64), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (__int64), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
+rm -f conftest.val
+else
+ ac_cv_sizeof___int64=0
fi
-echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6
-if test $ac_cv_header_stdc = yes; then
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof___int64" >&5
+echo "${ECHO_T}$ac_cv_sizeof___int64" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF___INT64 $ac_cv_sizeof___int64
+_ACEOF
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
+
+fi
+
+
+# ---------------------
+# Warnings and checking
+# ---------------------
+
+# Check $CC warning features (if it's GCC).
+# We want to use -pedantic, but we don't want warnings about
+# * 'long long'
+# * variadic macros
+# * overlong strings
+# So, we only use -pedantic if we can disable those warnings.
+
+echo "$as_me:$LINENO: checking whether ${CC} accepts -Wno-long-long" >&5
+echo $ECHO_N "checking whether ${CC} accepts -Wno-long-long... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_w_no_long_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-Wno-long-long"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_w_no_long_long=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_prog_cc_w_no_long_long=no
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_w_no_long_long" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_w_no_long_long" >&6
+echo "$as_me:$LINENO: checking whether ${CC} accepts -Wno-variadic-macros" >&5
+echo $ECHO_N "checking whether ${CC} accepts -Wno-variadic-macros... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_w_no_variadic_macros+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-Wno-variadic-macros"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_w_no_variadic_macros=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_prog_cc_w_no_variadic_macros=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_w_no_variadic_macros" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_w_no_variadic_macros" >&6
+echo "$as_me:$LINENO: checking whether ${CC} accepts -Wno-overlength-strings" >&5
+echo $ECHO_N "checking whether ${CC} accepts -Wno-overlength-strings... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_w_no_overlength_strings+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-Wno-overlength-strings"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_w_no_overlength_strings=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_prog_cc_w_no_overlength_strings=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_w_no_overlength_strings" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_w_no_overlength_strings" >&6
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
+strict1_warn=
+if test $ac_cv_prog_cc_w_no_long_long = yes \
+ && test $ac_cv_prog_cc_w_no_variadic_macros = yes \
+ && test $ac_cv_prog_cc_w_no_overlength_strings = yes ; then
+ strict1_warn="-pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings"
+fi
+
+# Add -Wold-style-definition if it's accepted
+echo "$as_me:$LINENO: checking whether ${CC} accepts -Wold-style-definition" >&5
+echo $ECHO_N "checking whether ${CC} accepts -Wold-style-definition... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_w_old_style_definition+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-Wold-style-definition"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -4279,26 +6295,320 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- eval "$as_ac_Header=yes"
+ ac_cv_prog_cc_w_old_style_definition=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-eval "$as_ac_Header=no"
+ac_cv_prog_cc_w_old_style_definition=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_w_old_style_definition" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_w_old_style_definition" >&6
+if test $ac_cv_prog_cc_w_old_style_definition = yes ; then
+ strict1_warn="${strict1_warn} -Wold-style-definition"
+fi
+
+# Add -Wmissing-format-attribute if it's accepted
+echo "$as_me:$LINENO: checking whether ${CC} accepts -Wmissing-format-attribute" >&5
+echo $ECHO_N "checking whether ${CC} accepts -Wmissing-format-attribute... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_w_missing_format_attribute+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-Wmissing-format-attribute"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_w_missing_format_attribute=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+ac_cv_prog_cc_w_missing_format_attribute=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_w_missing_format_attribute" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_w_missing_format_attribute" >&6
+if test $ac_cv_prog_cc_w_missing_format_attribute = yes ; then
+ strict1_warn="${strict1_warn} -Wmissing-format-attribute"
fi
+# Enable -Werror, period.
+# Check whether --enable-werror_always or --disable-werror_always was given.
+if test "${enable_werror_always+set}" = set; then
+ enableval="$enable_werror_always"
+
+else
+ enable_werror_always=no
+fi;
+if test x${enable_werror_always} = xyes ; then
+ strict1_warn="${strict1_warn} -Werror"
+ WERROR=-Werror
+fi
+
+
+
+# Get C++ compatibility warning flag, if supported.
+echo "$as_me:$LINENO: checking whether ${CC} accepts -Wc++-compat" >&5
+echo $ECHO_N "checking whether ${CC} accepts -Wc++-compat... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_w_cxx_compat+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="-Wc++-compat"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_w_cxx_compat=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_w_cxx_compat=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_w_cxx_compat" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_w_cxx_compat" >&6
+if test x${ac_cv_prog_cc_w_cxx_compat} = xyes; then
+ cxx_compat_warn="-Wc++-compat"
+fi
+
+
+
+# If the native compiler is GCC, we can enable warnings even in stage1.
+# That's useful for people building cross-compilers, or just running a
+# quick `make'.
+warn_cflags=
+if test "x$GCC" = "xyes"; then
+ warn_cflags='$(GCC_WARN_CFLAGS)'
+fi
+
+
+# Enable -Werror in bootstrap stage2 and later.
+is_release=
+if test x"`cat $srcdir/DEV-PHASE`" != xexperimental; then
+ is_release=yes
+fi
+# Check whether --enable-werror or --disable-werror was given.
+if test "${enable_werror+set}" = set; then
+ enableval="$enable_werror"
+
+else
+ if test x$is_release = x ; then
+ # Default to "yes" on development branches.
+ enable_werror=yes
+else
+ # Default to "no" on release branches.
+ enable_werror=no
+fi
+fi;
+if test x$enable_werror = xyes ; then
+ WERROR=-Werror
+fi
+
+
+# Enable expensive internal checks
+# Check whether --enable-checking or --disable-checking was given.
+if test "${enable_checking+set}" = set; then
+ enableval="$enable_checking"
+ ac_checking_flags="${enableval}"
+else
+
+# Determine the default checks.
+if test x$is_release = x ; then
+ ac_checking_flags=yes
+else
+ ac_checking_flags=release
+fi
+fi;
+ac_assert_checking=1
+ac_checking=
+ac_fold_checking=
+ac_gc_checking=
+ac_gc_always_collect=
+ac_rtl_checking=
+ac_rtlflag_checking=
+ac_runtime_checking=1
+ac_tree_checking=
+ac_valgrind_checking=
+IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="$IFS,"
+for check in $ac_checking_flags
+do
+ case $check in
+ # these set all the flags to specific states
+ yes) ac_assert_checking=1 ; ac_checking=1 ;
+ ac_fold_checking= ; ac_gc_checking=1 ;
+ ac_gc_always_collect= ; ac_rtl_checking= ;
+ ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
+ ac_tree_checking=1 ; ac_valgrind_checking= ;;
+ no|none) ac_assert_checking= ; ac_checking= ;
+ ac_fold_checking= ; ac_gc_checking= ;
+ ac_gc_always_collect= ; ac_rtl_checking= ;
+ ac_rtlflag_checking= ; ac_runtime_checking= ;
+ ac_tree_checking= ; ac_valgrind_checking= ;;
+ all) ac_assert_checking=1 ; ac_checking=1 ;
+ ac_fold_checking=1 ; ac_gc_checking=1 ;
+ ac_gc_always_collect=1 ; ac_rtl_checking=1 ;
+ ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
+ ac_tree_checking=1 ; ac_valgrind_checking= ;;
+ release) ac_assert_checking=1 ; ac_checking= ;
+ ac_fold_checking= ; ac_gc_checking= ;
+ ac_gc_always_collect= ; ac_rtl_checking= ;
+ ac_rtlflag_checking= ; ac_runtime_checking=1 ;
+ ac_tree_checking= ; ac_valgrind_checking= ;;
+ # these enable particular checks
+ assert) ac_assert_checking=1 ;;
+ fold) ac_fold_checking=1 ;;
+ gc) ac_gc_checking=1 ;;
+ gcac) ac_gc_always_collect=1 ;;
+ misc) ac_checking=1 ;;
+ rtl) ac_rtl_checking=1 ;;
+ rtlflag) ac_rtlflag_checking=1 ;;
+ runtime) ac_runtime_checking=1 ;;
+ tree) ac_tree_checking=1 ;;
+ valgrind) ac_valgrind_checking=1 ;;
+ *) { { echo "$as_me:$LINENO: error: unknown check category $check" >&5
+echo "$as_me: error: unknown check category $check" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
done
+IFS="$ac_save_IFS"
+
+nocommon_flag=""
+if test x$ac_checking != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_CHECKING 1
+_ACEOF
+
+ nocommon_flag=-fno-common
+fi
+
+if test x$ac_assert_checking != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_ASSERT_CHECKING 1
+_ACEOF
+
+fi
+
+if test x$ac_runtime_checking != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_RUNTIME_CHECKING 1
+_ACEOF
+
+fi
+if test x$ac_tree_checking != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_TREE_CHECKING 1
+_ACEOF
+
+ TREEBROWSER=tree-browser.o
+fi
+
+if test x$ac_rtl_checking != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_RTL_CHECKING 1
+_ACEOF
+
+fi
+if test x$ac_rtlflag_checking != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_RTL_FLAG_CHECKING 1
+_ACEOF
+
+fi
+if test x$ac_gc_checking != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_GC_CHECKING 1
+_ACEOF
+fi
+if test x$ac_gc_always_collect != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_GC_ALWAYS_COLLECT 1
+_ACEOF
+
+fi
+if test x$ac_fold_checking != x ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_FOLD_CHECKING 1
+_ACEOF
+
+fi
+valgrind_path_defines=
+valgrind_command=
if test "${ac_cv_header_valgrind_h+set}" = set; then
echo "$as_me:$LINENO: checking for valgrind.h" >&5
@@ -4445,7 +6755,7 @@ fi
-if test x$ac_checking_valgrind != x ; then
+if test x$ac_valgrind_checking != x ; then
# It is certainly possible that there's valgrind but no valgrind.h.
# GCC relies on making annotations so we must have both.
echo "$as_me:$LINENO: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5
@@ -4630,22 +6940,42 @@ fi
+# Check whether --enable-mapped-location or --disable-mapped-location was given.
+if test "${enable_mapped_location+set}" = set; then
+ enableval="$enable_mapped_location"
+
+else
+ enable_mapped_location=no
+fi;
+
+if test "$enable_mapped_location" = yes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_MAPPED_LOCATION 1
+_ACEOF
+
+fi
+
# Enable code coverage collection
# Check whether --enable-coverage or --disable-coverage was given.
if test "${enable_coverage+set}" = set; then
enableval="$enable_coverage"
case "${enableval}" in
-yes|noopt)
- coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O0"
- ;;
-opt)
- coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O2"
- ;;
-*)
- { { echo "$as_me:$LINENO: error: unknown coverage setting $enableval" >&5
+ yes|noopt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O0"
+ ;;
+ opt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O2"
+ ;;
+ no)
+ # a.k.a. --disable-coverage
+ coverage_flags=""
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown coverage setting $enableval" >&5
echo "$as_me: error: unknown coverage setting $enableval" >&2;}
{ (exit 1); exit 1; }; }
- ;;
+ ;;
esac
else
coverage_flags=""
@@ -4698,6 +7028,37 @@ if test "${enable___cxa_atexit+set}" = set; then
fi;
+# Enable C extension for decimal float if target supports it.
+# Check whether --enable-decimal-float or --disable-decimal-float was given.
+if test "${enable_decimal_float+set}" = set; then
+ enableval="$enable_decimal_float"
+
+ if test x$enablevar = xyes ; then
+ case $target in
+ powerpc*-*-linux* | i?86*-*-linux*)
+ enable_decimal_float=yes
+ ;;
+ *)
+ { echo "$as_me:$LINENO: WARNING: decimal float is not supported for this target" >&5
+echo "$as_me: WARNING: decimal float is not supported for this target" >&2;}
+ enable_decimal_float=no
+ ;;
+ esac
+ fi
+
+else
+ enable_decimal_float=no
+fi;
+
+
+
+dfp=`if test $enable_decimal_float = yes; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_DECIMAL_FLOAT $dfp
+_ACEOF
+
+
# Enable threads
# Pass with no value to take the default
# Pass with a value to specify a thread package
@@ -4708,8 +7069,23 @@ if test "${enable_threads+set}" = set; then
else
enable_threads=''
fi;
-# Save in case it gets overwritten in config.gcc
-enable_threads_flag=$enable_threads
+
+# Check whether --enable-tls or --disable-tls was given.
+if test "${enable_tls+set}" = set; then
+ enableval="$enable_tls"
+
+ case $enable_tls in
+ yes | no) ;;
+ *) { { echo "$as_me:$LINENO: error: '$enable_tls' is an invalid value for --enable-tls.
+Valid choices are 'yes' and 'no'." >&5
+echo "$as_me: error: '$enable_tls' is an invalid value for --enable-tls.
+Valid choices are 'yes' and 'no'." >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+
+else
+ enable_tls=''
+fi;
# Check whether --enable-objc-gc or --disable-objc-gc was given.
if test "${enable_objc_gc+set}" = set; then
@@ -4756,6 +7132,13 @@ fi;
+# Check whether --with-build-sysroot or --without-build-sysroot was given.
+if test "${with_build_sysroot+set}" = set; then
+ withval="$with_build_sysroot"
+
+fi;
+
+
# Check whether --with-sysroot or --without-sysroot was given.
if test "${with_sysroot+set}" = set; then
withval="$with_sysroot"
@@ -4809,6 +7192,38 @@ else
fi;
+# Sanity check enable_languages in case someone does not run the toplevel
+# configure # script.
+# Check whether --enable-languages or --disable-languages was given.
+if test "${enable_languages+set}" = set; then
+ enableval="$enable_languages"
+ case ,${enable_languages}, in
+ ,,|,yes,)
+ # go safe -- we cannot be much sure without the toplevel
+ # configure's
+ # analysis of which target libs are present and usable
+ enable_languages=c
+ ;;
+ *,all,*)
+ { { echo "$as_me:$LINENO: error: only the toplevel supports --enable-languages=all" >&5
+echo "$as_me: error: only the toplevel supports --enable-languages=all" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ *,c,*)
+ ;;
+ *)
+ enable_languages=c,${enable_languages}
+ ;;
+esac
+else
+ enable_languages=c
+fi;
+
+# Used by documentation targets
+
+
+
+
# -------------------------
# Checks for other programs
# -------------------------
@@ -4884,7 +7299,7 @@ fi
test -n "$AWK" && break
done
-# We need awk to run opts.sh (to create options.c and options.h).
+# We need awk to create options.c and options.h.
# Bail out if it's missing.
case ${AWK} in
"") { { echo "$as_me:$LINENO: error: can't build without awk, bailing out" >&5
@@ -4892,74 +7307,70 @@ echo "$as_me: error: can't build without awk, bailing out" >&2;}
{ (exit 1); exit 1; }; } ;;
esac
-echo "$as_me:$LINENO: checking whether ln works" >&5
-echo $ECHO_N "checking whether ln works... $ECHO_C" >&6
-if test "${gcc_cv_prog_LN+set}" = set; then
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+if test "${gcc_cv_prog_LN_S+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
rm -f conftestdata_t
echo >conftestdata_f
-if ln conftestdata_f conftestdata_t 2>/dev/null
+if ln -s conftestdata_f conftestdata_t 2>/dev/null
then
- gcc_cv_prog_LN="ln"
+ gcc_cv_prog_LN_S="ln -s"
else
- if ln -s conftestdata_f conftestdata_t 2>/dev/null
+ if ln conftestdata_f conftestdata_t 2>/dev/null
then
- gcc_cv_prog_LN="ln -s"
+ gcc_cv_prog_LN_S=ln
else
- gcc_cv_prog_LN=cp
+ if cp -p conftestdata_f conftestdata_t 2>/dev/null
+ then
+ gcc_cv_prog_LN_S="cp -p"
+ else
+ gcc_cv_prog_LN_S=cp
+ fi
fi
fi
rm -f conftestdata_f conftestdata_t
fi
-LN="$gcc_cv_prog_LN"
-if test "$gcc_cv_prog_LN" = "ln"; then
+LN_S="$gcc_cv_prog_LN_S"
+if test "$gcc_cv_prog_LN_S" = "ln -s"; then
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
else
- if test "$gcc_cv_prog_LN" = "ln -s"; then
- echo "$as_me:$LINENO: result: no, using ln -s" >&5
-echo "${ECHO_T}no, using ln -s" >&6
+ if test "$gcc_cv_prog_LN_S" = "ln"; then
+ echo "$as_me:$LINENO: result: no, using ln" >&5
+echo "${ECHO_T}no, using ln" >&6
else
- echo "$as_me:$LINENO: result: no, and neither does ln -s, so using cp" >&5
-echo "${ECHO_T}no, and neither does ln -s, so using cp" >&6
+ echo "$as_me:$LINENO: result: no, and neither does ln, so using $gcc_cv_prog_LN_S" >&5
+echo "${ECHO_T}no, and neither does ln, so using $gcc_cv_prog_LN_S" >&6
fi
fi
-echo "$as_me:$LINENO: checking whether ln -s works" >&5
-echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
-if test "${gcc_cv_prog_LN_S+set}" = set; then
+echo "$as_me:$LINENO: checking whether ln works" >&5
+echo $ECHO_N "checking whether ln works... $ECHO_C" >&6
+if test "${acx_cv_prog_LN+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
rm -f conftestdata_t
echo >conftestdata_f
-if ln -s conftestdata_f conftestdata_t 2>/dev/null
+if ln conftestdata_f conftestdata_t 2>/dev/null
then
- gcc_cv_prog_LN_S="ln -s"
+ acx_cv_prog_LN=ln
else
- if ln conftestdata_f conftestdata_t 2>/dev/null
- then
- gcc_cv_prog_LN_S=ln
- else
- gcc_cv_prog_LN_S=cp
- fi
+ acx_cv_prog_LN=no
fi
rm -f conftestdata_f conftestdata_t
fi
-LN_S="$gcc_cv_prog_LN_S"
-if test "$gcc_cv_prog_LN_S" = "ln -s"; then
+if test $acx_cv_prog_LN = no; then
+ LN="$LN_S"
+ echo "$as_me:$LINENO: result: no, using $LN" >&5
+echo "${ECHO_T}no, using $LN" >&6
+else
+ LN="$acx_cv_prog_LN"
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
-else
- if test "$gcc_cv_prog_LN_S" = "ln"; then
- echo "$as_me:$LINENO: result: no, using ln" >&5
-echo "${ECHO_T}no, using ln" >&6
- else
- echo "$as_me:$LINENO: result: no, and neither does ln, so using cp" >&5
-echo "${ECHO_T}no, and neither does ln, so using cp" >&6
- fi
fi
if test -n "$ac_tool_prefix"; then
@@ -5042,6 +7453,19 @@ else
RANLIB="$ac_cv_prog_RANLIB"
fi
+case "${host}" in
+*-*-darwin*)
+ # By default, the Darwin ranlib will not treat common symbols as
+ # definitions when building the archive table of contents. Other
+ # ranlibs do that; pass an option to the Darwin ranlib that makes
+ # it behave similarly.
+ ranlib_flags="-c"
+ ;;
+*)
+ ranlib_flags=""
+esac
+
+
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
@@ -5176,16 +7600,14 @@ echo "${ECHO_T}no" >&6
fi
-# Do we have a single-tree copy of texinfo?
-if test -f $srcdir/../texinfo/Makefile.in; then
- MAKEINFO='$(objdir)/../texinfo/makeinfo/makeinfo'
- gcc_cv_prog_makeinfo_modern=yes
- echo "$as_me:$LINENO: result: Using makeinfo from the unified source tree." >&5
-echo "${ECHO_T}Using makeinfo from the unified source tree." >&6
-else
- # See if makeinfo has been installed and is modern enough
- # that we can use it.
- # Extract the first word of "makeinfo", so it can be a program name with args.
+MISSING="${CONFIG_SHELL-/bin/sh} $srcdir/../missing"
+
+# See if makeinfo has been installed and is modern enough
+# that we can use it.
+
+ac_executable_extensions="$build_exeext"
+
+# Extract the first word of "makeinfo", so it can be a program name with args.
set dummy makeinfo; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
@@ -5229,10 +7651,10 @@ if test "${gcc_cv_prog_makeinfo_modern+set}" = set; then
else
ac_prog_version=`$MAKEINFO --version 2>&1 |
sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'`
- echo "configure:5232: version of makeinfo is $ac_prog_version" >&5
+ echo "configure:7654: version of makeinfo is $ac_prog_version" >&5
case $ac_prog_version in
'') gcc_cv_prog_makeinfo_modern=no;;
- 4.[2-9]*)
+ 4.[4-9]*)
gcc_cv_prog_makeinfo_modern=yes;;
*) gcc_cv_prog_makeinfo_modern=no;;
esac
@@ -5244,9 +7666,8 @@ else
gcc_cv_prog_makeinfo_modern=no
fi
-fi
-
if test $gcc_cv_prog_makeinfo_modern = no; then
+ MAKEINFO="$MISSING makeinfo"
{ echo "$as_me:$LINENO: WARNING:
*** Makeinfo is missing or too old.
*** Info documentation will not be built." >&5
@@ -5258,6 +7679,7 @@ else
BUILD_INFO=info
fi
+
# Is pod2man recent enough to regenerate manpages?
echo "$as_me:$LINENO: checking for recent Pod::Man" >&5
echo $ECHO_N "checking for recent Pod::Man... $ECHO_C" >&6
@@ -5271,12 +7693,12 @@ echo "${ECHO_T}no" >&6
GENERATED_MANPAGES=
fi
+
# How about lex?
-if test -f $srcdir/../flex/skel.c; then
- FLEX='$(objdir)/../flex/flex'
-else
- # Extract the first word of "flex", so it can be a program name with args.
-set dummy flex; ac_word=$2
+for ac_prog in flex
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_FLEX+set}" = set; then
@@ -5292,14 +7714,13 @@ do
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_FLEX="flex"
+ ac_cv_prog_FLEX="$ac_prog"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
- test -z "$ac_cv_prog_FLEX" && ac_cv_prog_FLEX="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing flex"
fi
fi
FLEX=$ac_cv_prog_FLEX
@@ -5311,15 +7732,16 @@ else
echo "${ECHO_T}no" >&6
fi
-fi
+ test -n "$FLEX" && break
+done
+test -n "$FLEX" || FLEX="$MISSING flex"
+
# Bison?
-# The -L switch is so bison can find its skeleton file.
-if test -f $srcdir/../bison/bison.simple; then
- BISON='$(objdir)/../bison/bison -L $(srcdir)/../bison/'
-else
- # Extract the first word of "bison", so it can be a program name with args.
-set dummy bison; ac_word=$2
+for ac_prog in bison
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
echo "$as_me:$LINENO: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_BISON+set}" = set; then
@@ -5335,14 +7757,13 @@ do
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_BISON="bison"
+ ac_cv_prog_BISON="$ac_prog"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
- test -z "$ac_cv_prog_BISON" && ac_cv_prog_BISON="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing bison"
fi
fi
BISON=$ac_cv_prog_BISON
@@ -5354,8 +7775,101 @@ else
echo "${ECHO_T}no" >&6
fi
+ test -n "$BISON" && break
+done
+test -n "$BISON" || BISON="$MISSING bison"
+
+
+# Binutils are not build modules, unlike bison/flex/makeinfo. So we
+# check for build == host before using them.
+
+# NM
+if test x${build} = x${host} && test -f $srcdir/../binutils/nm.c \
+ && test -d ../binutils ; then
+ NM='$(objdir)/../binutils/nm-new'
+else
+ # Extract the first word of "nm", so it can be a program name with args.
+set dummy nm; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_NM+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$NM"; then
+ ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_NM="nm"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_NM" && ac_cv_prog_NM="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing nm"
+fi
+fi
+NM=$ac_cv_prog_NM
+if test -n "$NM"; then
+ echo "$as_me:$LINENO: result: $NM" >&5
+echo "${ECHO_T}$NM" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+
+# AR
+if test x${build} = x${host} && test -f $srcdir/../binutils/ar.c \
+ && test -d ../binutils ; then
+ AR='$(objdir)/../binutils/ar'
+else
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing ar"
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
fi
+
# --------------------
# Checks for C headers
# --------------------
@@ -5661,67 +8175,6 @@ _ACEOF
fi
-echo "$as_me:$LINENO: checking for working stdbool.h" >&5
-echo $ECHO_N "checking for working stdbool.h... $ECHO_C" >&6
-if test "${ac_cv_header_stdbool_h+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdbool.h>
-int
-main ()
-{
-bool foo = false;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_header_stdbool_h=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_header_stdbool_h=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5
-echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6
-if test $ac_cv_header_stdbool_h = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_STDBOOL_H 1
-_ACEOF
-
-fi
-
echo "$as_me:$LINENO: checking whether string.h and strings.h may both be included" >&5
echo $ECHO_N "checking whether string.h and strings.h may both be included... $ECHO_C" >&6
if test "${gcc_cv_header_string+set}" = set; then
@@ -5876,7 +8329,8 @@ fi
-for ac_header in limits.h stddef.h string.h strings.h stdlib.h time.h \
+
+for ac_header in limits.h stddef.h string.h strings.h stdlib.h time.h iconv.h \
fcntl.h unistd.h sys/file.h sys/time.h sys/mman.h \
sys/resource.h sys/param.h sys/times.h sys/stat.h \
direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h
@@ -6142,8 +8596,7 @@ echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
if test "${ac_cv_c_bigendian+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_cv_c_bigendian=unknown
-# See if sys/param.h defines the BYTE_ORDER macro.
+ # See if sys/param.h defines the BYTE_ORDER macro.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
@@ -6152,13 +8605,14 @@ cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/param.h>
+
int
main ()
{
-
#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
bogus endian macros
#endif
+
;
return 0;
}
@@ -6194,13 +8648,14 @@ cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/param.h>
+
int
main ()
{
-
#if BYTE_ORDER != BIG_ENDIAN
not big endian
#endif
+
;
return 0;
}
@@ -6239,11 +8694,69 @@ else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-if test $ac_cv_c_bigendian = unknown; then
-if test "$cross_compiling" = yes; then
- echo $ac_n "cross-compiling... " 2>&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
@@ -6251,7 +8764,9 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-main () {
+int
+main ()
+{
/* Are we little or big endian? From Harbison&Steele. */
union
{
@@ -6285,67 +8800,26 @@ fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
echo "${ECHO_T}$ac_cv_c_bigendian" >&6
-if test $ac_cv_c_bigendian = unknown; then
-echo "$as_me:$LINENO: checking to probe for byte ordering" >&5
-echo $ECHO_N "checking to probe for byte ordering... $ECHO_C" >&6
-
-cat >conftest.c <<EOF
-short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
-short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
-void _ascii() { char* s = (char*) ascii_mm; s = (char*) ascii_ii; }
-short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
-short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
-void _ebcdic() { char* s = (char*) ebcdic_mm; s = (char*) ebcdic_ii; }
-int main() { _ascii (); _ebcdic (); return 0; }
-EOF
- if test -f conftest.c ; then
- if ${CC-cc} ${CFLAGS} conftest.c -o conftest.o && test -f conftest.o ; then
- if test `grep -l BIGenDianSyS conftest.o` ; then
- echo $ac_n ' big endian probe OK, ' 1>&6
- ac_cv_c_bigendian=yes
- fi
- if test `grep -l LiTTleEnDian conftest.o` ; then
- echo $ac_n ' little endian probe OK, ' 1>&6
- if test $ac_cv_c_bigendian = yes ; then
- ac_cv_c_bigendian=unknown;
- else
- ac_cv_c_bigendian=no
- fi
- fi
- echo $ac_n 'guessing bigendian ... ' >&6
- fi
- fi
-echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
-echo "${ECHO_T}$ac_cv_c_bigendian" >&6
-fi
-if test $ac_cv_c_bigendian = yes; then
+case $ac_cv_c_bigendian in
+ yes)
cat >>confdefs.h <<\_ACEOF
#define WORDS_BIGENDIAN 1
_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HOST_WORDS_BIG_ENDIAN 1
-_ACEOF
-
- BYTEORDER=4321
-else
- BYTEORDER=1234
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define BYTEORDER $BYTEORDER
-_ACEOF
-
-if test $ac_cv_c_bigendian = unknown; then
- { { echo "$as_me:$LINENO: error: unknown endianess - sorry" >&5
-echo "$as_me: error: unknown endianess - sorry" >&2;}
- { (exit please pre-set ac_cv_c_bigendian); exit please pre-set ac_cv_c_bigendian; }; }
-fi
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
# --------
@@ -6363,13 +8837,6 @@ vax-*-*)
stage1_cflags="-J"
fi
;;
-powerpc-*-darwin*)
- # The spiffy cpp-precomp chokes on some legitimate constructs in GCC
- # sources; use -no-cpp-precomp to get to GNU cpp.
- # Apple's GCC has bugs in designated initializer handling, so disable
- # that too.
- stage1_cflags="-no-cpp-precomp -DHAVE_DESIGNATED_INITIALIZERS=0"
- ;;
esac
@@ -6809,11 +9276,21 @@ fi
-for ac_func in times clock dup2 kill getrlimit setrlimit atoll atoq \
- sysconf strsignal putc_unlocked fputc_unlocked fputs_unlocked \
- fwrite_unlocked fprintf_unlocked getrusage nl_langinfo \
- scandir alphasort gettimeofday mbstowcs wcswidth mmap mincore \
- setlocale
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in times clock kill getrlimit setrlimit atoll atoq \
+ sysconf strsignal getrusage nl_langinfo scandir alphasort \
+ gettimeofday mbstowcs wcswidth mmap mincore setlocale \
+ clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -7182,13 +9659,59 @@ else
fi
-echo "$as_me:$LINENO: checking whether the printf functions support %p" >&5
-echo $ECHO_N "checking whether the printf functions support %p... $ECHO_C" >&6
-if test "${gcc_cv_func_printf_ptr+set}" = set; then
+
+echo "$as_me:$LINENO: checking for sys/mman.h" >&5
+echo $ECHO_N "checking for sys/mman.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_mman_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- if test "$cross_compiling" = yes; then
- gcc_cv_func_printf_ptr=no
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/mman.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_cv_header_sys_mman_h=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_sys_mman_h=no
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_mman_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_mman_h" >&6
+if test $ac_cv_header_sys_mman_h = yes; then
+ gcc_header_sys_mman_h=yes
+else
+ gcc_header_sys_mman_h=no
+fi
+
+echo "$as_me:$LINENO: checking for mmap" >&5
+echo $ECHO_N "checking for mmap... $ECHO_C" >&6
+if test "${ac_cv_func_mmap+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
@@ -7196,53 +9719,93 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
-#include <stdio.h>
+/* Define mmap to an innocuous variant, in case <limits.h> declares mmap.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define mmap innocuous_mmap
-int main()
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char mmap (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef mmap
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
{
- char buf[64];
- char *p = buf, *q = NULL;
- sprintf(buf, "%p", p);
- sscanf(buf, "%p", &q);
- return (p != q);
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char mmap ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_mmap) || defined (__stub___mmap)
+choke me
+#else
+char (*f) () = mmap;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != mmap;
+ ;
+ return 0;
}
_ACEOF
-rm -f conftest$ac_exeext
+rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
+ (eval $ac_link) 2>conftest.er1
ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- gcc_cv_func_printf_ptr=yes
+ ac_cv_func_mmap=yes
else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
+ echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-( exit $ac_status )
-gcc_cv_func_printf_ptr=no
+ac_cv_func_mmap=no
fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core core.* *.core
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $gcc_cv_func_printf_ptr" >&5
-echo "${ECHO_T}$gcc_cv_func_printf_ptr" >&6
-if test $gcc_cv_func_printf_ptr = yes ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_PRINTF_PTR 1
-_ACEOF
-
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap" >&5
+echo "${ECHO_T}$ac_cv_func_mmap" >&6
+if test $ac_cv_func_mmap = yes; then
+ gcc_func_mmap=yes
+else
+ gcc_func_mmap=no
fi
-if test $ac_cv_header_sys_mman_h != yes \
- || test $ac_cv_func_mmap != yes; then
+if test "$gcc_header_sys_mman_h" != yes \
+ || test "$gcc_func_mmap" != yes; then
gcc_cv_func_mmap_file=no
gcc_cv_func_mmap_dev_zero=no
gcc_cv_func_mmap_anon=no
@@ -7866,73 +10429,576 @@ fi
-
- am_cv_lib_iconv_ldpath=
-
-# Check whether --with-libiconv-prefix or --without-libiconv-prefix was given.
-if test "${with_libiconv_prefix+set}" = set; then
- withval="$with_libiconv_prefix"
-
- for dir in `echo "$withval" | tr : ' '`; do
- if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
- if test -d $dir/lib; then am_cv_lib_iconv_ldpath="-L$dir/lib"; fi
- done
-
-fi;
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
-for ac_header in iconv.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ with_gnu_ld=no
+fi;
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
else
- ac_cpp_err=
+ PATH_SEPARATOR=:
fi
+ rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
else
- ac_cpp_err=yes
+ echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
fi
-if test -z "$ac_cpp_err"; then
- eval "$as_ac_Header=yes"
+if test "${acl_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- eval "$as_ac_Header=no"
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
fi
-rm -f conftest.err conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
-done
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${acl_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ acl_cv_prog_gnu_ld=yes
+else
+ acl_cv_prog_gnu_ld=no
+fi
+fi
+echo "$as_me:$LINENO: result: $acl_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$acl_cv_prog_gnu_ld" >&6
+with_gnu_ld=$acl_cv_prog_gnu_ld
+
+
+
+ echo "$as_me:$LINENO: checking for shared library run path origin" >&5
+echo $ECHO_N "checking for shared library run path origin... $ECHO_C" >&6
+if test "${acl_cv_rpath+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+
+fi
+echo "$as_me:$LINENO: result: $acl_cv_rpath" >&5
+echo "${ECHO_T}$acl_cv_rpath" >&6
+ wl="$acl_cv_wl"
+ libext="$acl_cv_libext"
+ shlibext="$acl_cv_shlibext"
+ hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ hardcode_direct="$acl_cv_hardcode_direct"
+ hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ # Check whether --enable-rpath or --disable-rpath was given.
+if test "${enable_rpath+set}" = set; then
+ enableval="$enable_rpath"
+ :
+else
+ enable_rpath=yes
+fi;
+
+
+
+
+
+
+
+ use_additional=yes
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+
+# Check whether --with-libiconv-prefix or --without-libiconv-prefix was given.
+if test "${with_libiconv_prefix+set}" = set; then
+ withval="$with_libiconv_prefix"
+
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/lib"
+ fi
+ fi
+
+fi;
+ LIBICONV=
+ LTLIBICONV=
+ INCICONV=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='iconv '
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value"
+ else
+ :
+ fi
+ else
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ if test $use_additional = yes; then
+ if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
+ found_dir="$additional_libdir"
+ found_so="$additional_libdir/lib$name.$shlibext"
+ if test -f "$additional_libdir/lib$name.la"; then
+ found_la="$additional_libdir/lib$name.la"
+ fi
+ else
+ if test -f "$additional_libdir/lib$name.$libext"; then
+ found_dir="$additional_libdir"
+ found_a="$additional_libdir/lib$name.$libext"
+ if test -f "$additional_libdir/lib$name.la"; then
+ found_la="$additional_libdir/lib$name.la"
+ fi
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
+ found_dir="$dir"
+ found_so="$dir/lib$name.$shlibext"
+ if test -f "$dir/lib$name.la"; then
+ found_la="$dir/lib$name.la"
+ fi
+ else
+ if test -f "$dir/lib$name.$libext"; then
+ found_dir="$dir"
+ found_a="$dir/lib$name.$libext"
+ if test -f "$dir/lib$name.la"; then
+ found_la="$dir/lib$name.la"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ if test "$hardcode_direct" = yes; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ haveit=
+ for x in $LDFLAGS $LIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir"
+ fi
+ if test "$hardcode_minus_L" != no; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name"
+ fi
+ fi
+ additional_includedir=
+ case "$found_dir" in
+ */lib | */lib/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INCICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ if test -n "$found_la"; then
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ if test "X$additional_libdir" != "X/usr/lib"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/lib"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$dep"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name"
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$hardcode_libdir_separator"; then
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+ else
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ for found_dir in $ltrpathdirs; do
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir"
+ done
+ fi
+
+
+
+
+
+
+
+ am_save_CPPFLAGS="$CPPFLAGS"
+
+ for element in $INCICONV; do
+ haveit=
+ for x in $CPPFLAGS; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+ fi
+ done
echo "$as_me:$LINENO: checking for iconv" >&5
@@ -7993,7 +11059,7 @@ rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
if test "$am_cv_func_iconv" != yes; then
am_save_LIBS="$LIBS"
- LIBS="$LIBS $am_cv_libiconv_ldpath -liconv"
+ LIBS="$LIBS $LIBICONV"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
@@ -8055,6 +11121,21 @@ cat >>confdefs.h <<\_ACEOF
#define HAVE_ICONV 1
_ACEOF
+ fi
+ if test "$am_cv_lib_iconv" = yes; then
+ echo "$as_me:$LINENO: checking how to link with libiconv" >&5
+echo $ECHO_N "checking how to link with libiconv... $ECHO_C" >&6
+ echo "$as_me:$LINENO: result: $LIBICONV" >&5
+echo "${ECHO_T}$LIBICONV" >&6
+ else
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBICONV=
+ LTLIBICONV=
+ fi
+
+
+
+ if test "$am_cv_func_iconv" = yes; then
echo "$as_me:$LINENO: checking for iconv declaration" >&5
echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6
if test "${am_cv_proto_iconv+set}" = set; then
@@ -8132,11 +11213,6 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
fi
- LIBICONV=
- if test "$am_cv_lib_iconv" = yes; then
- LIBICONV="$am_cv_lib_iconv_ldpath -liconv"
- fi
-
# Until we have in-tree GNU iconv:
LIBICONV_DEP=
@@ -8206,15 +11282,119 @@ _ACEOF
fi
+
+ echo "$as_me:$LINENO: checking for nl_langinfo and CODESET" >&5
+echo $ECHO_N "checking for nl_langinfo and CODESET... $ECHO_C" >&6
+if test "${am_cv_langinfo_codeset+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <langinfo.h>
+int
+main ()
+{
+char* cs = nl_langinfo(CODESET);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ am_cv_langinfo_codeset=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+am_cv_langinfo_codeset=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_langinfo_codeset" >&5
+echo "${ECHO_T}$am_cv_langinfo_codeset" >&6
+ if test $am_cv_langinfo_codeset = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LANGINFO_CODESET 1
+_ACEOF
+
+ fi
+
+
# We will need to find libiberty.h and ansidecl.h
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
-for ac_func in getenv atol sbrk abort atof getcwd getwd \
- strsignal putc_unlocked fputs_unlocked fwrite_unlocked \
- fprintf_unlocked strstr errno snprintf vasprintf \
- malloc realloc calloc free basename getopt clock
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in getenv atol asprintf sbrk abort atof getcwd getwd \
+ strsignal strstr strverscmp \
+ errno snprintf vsnprintf vasprintf malloc realloc calloc \
+ free basename getopt clock getpagesize clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked
do
- ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ ac_tr_decl=`echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
echo "$as_me:$LINENO: checking whether $ac_func is declared" >&5
echo $ECHO_N "checking whether $ac_func is declared... $ECHO_C" >&6
if eval "test \"\${gcc_cv_have_decl_$ac_func+set}\" = set"; then
@@ -8289,108 +11469,14 @@ _ACEOF
fi
done
-if test x = y ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_GETENV 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_ATOL 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_SBRK 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_ABORT 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_ATOF 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_GETCWD 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_GETWD 1
-_ACEOF
- \
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_STRSIGNAL 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_PUTC_UNLOCKED 1
-_ACEOF
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_FPUTS_UNLOCKED 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_FWRITE_UNLOCKED 1
-_ACEOF
- \
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_FPRINTF_UNLOCKED 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_STRSTR 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_ERRNO 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_SNPRINTF 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_VASPRINTF 1
-_ACEOF
- \
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_MALLOC 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_REALLOC 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_CALLOC 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_FREE 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_BASENAME 1
-_ACEOF
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_GETOPT 1
-_ACEOF
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_CLOCK 1
-_ACEOF
-fi
for ac_func in getrlimit setrlimit getrusage
do
- ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ ac_tr_decl=`echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
echo "$as_me:$LINENO: checking whether $ac_func is declared" >&5
echo $ECHO_N "checking whether $ac_func is declared... $ECHO_C" >&6
if eval "test \"\${gcc_cv_have_decl_$ac_func+set}\" = set"; then
@@ -8469,20 +11555,6 @@ _ACEOF
fi
done
-if test x = y ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_GETRLIMIT 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_SETRLIMIT 1
-_ACEOF
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_GETRUSAGE 1
-_ACEOF
-fi
cat >conftest.$ac_ext <<_ACEOF
@@ -8541,9 +11613,14 @@ _ACEOF
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# On AIX 5.2, <ldfcn.h> conflicts with <fcntl.h>, as both define incompatible
+# FREAD and FWRITE macros. Fortunately, for GCC's single usage of ldgetname
+# in collect2.c, <fcntl.h> isn't visible, but the configure test below needs
+# to undef these macros to get the correct value for HAVE_DECL_LDGETNAME.
+
for ac_func in ldgetname
do
- ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ ac_tr_decl=`echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
echo "$as_me:$LINENO: checking whether $ac_func is declared" >&5
echo $ECHO_N "checking whether $ac_func is declared... $ECHO_C" >&6
if eval "test \"\${gcc_cv_have_decl_$ac_func+set}\" = set"; then
@@ -8561,6 +11638,8 @@ cat >>conftest.$ac_ext <<_ACEOF
#include "ansidecl.h"
#include "system.h"
#ifdef HAVE_LDFCN_H
+#undef FREAD
+#undef FWRITE
#include <ldfcn.h>
#endif
@@ -8622,17 +11701,12 @@ _ACEOF
fi
done
-if test x = y ; then
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_LDGETNAME 1
-_ACEOF
-fi
for ac_func in times
do
- ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ ac_tr_decl=`echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
echo "$as_me:$LINENO: checking whether $ac_func is declared" >&5
echo $ECHO_N "checking whether $ac_func is declared... $ECHO_C" >&6
if eval "test \"\${gcc_cv_have_decl_$ac_func+set}\" = set"; then
@@ -8711,38 +11785,37 @@ _ACEOF
fi
done
-if test x = y ; then
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DECL_TIMES 1
-_ACEOF
-fi
-# More time-related stuff.
-echo "$as_me:$LINENO: checking for struct tms" >&5
-echo $ECHO_N "checking for struct tms... $ECHO_C" >&6
-if test "${ac_cv_struct_tms+set}" = set; then
+for ac_func in sigaltstack
+do
+ ac_tr_decl=`echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+echo "$as_me:$LINENO: checking whether $ac_func is declared" >&5
+echo $ECHO_N "checking whether $ac_func is declared... $ECHO_C" >&6
+if eval "test \"\${gcc_cv_have_decl_$ac_func+set}\" = set"; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
-cat >conftest.$ac_ext <<_ACEOF
+ cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
#include "ansidecl.h"
#include "system.h"
-#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
-#endif
+#include <signal.h>
+
int
main ()
{
-struct tms tms;
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
;
return 0;
}
@@ -8769,30 +11842,37 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_struct_tms=yes
+ eval "gcc_cv_have_decl_$ac_func=yes"
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-ac_cv_struct_tms=no
+eval "gcc_cv_have_decl_$ac_func=no"
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $ac_cv_struct_tms" >&5
-echo "${ECHO_T}$ac_cv_struct_tms" >&6
-if test $ac_cv_struct_tms = yes; then
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_STRUCT_TMS 1
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6 ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6 ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
_ACEOF
fi
-# use gcc_cv_* here because this doesn't match the behavior of AC_CHECK_TYPE.
-# revisit after autoconf 2.50.
-echo "$as_me:$LINENO: checking for clock_t" >&5
-echo $ECHO_N "checking for clock_t... $ECHO_C" >&6
-if test "${gcc_cv_type_clock_t+set}" = set; then
+done
+
+
+# More time-related stuff.
+echo "$as_me:$LINENO: checking for struct tms" >&5
+echo $ECHO_N "checking for struct tms... $ECHO_C" >&6
+if test "${ac_cv_struct_tms+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
@@ -8805,11 +11885,14 @@ cat >>conftest.$ac_ext <<_ACEOF
#include "ansidecl.h"
#include "system.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
int
main ()
{
-clock_t x;
+struct tms tms;
;
return 0;
}
@@ -8836,31 +11919,34 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- gcc_cv_type_clock_t=yes
+ ac_cv_struct_tms=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-gcc_cv_type_clock_t=no
+ac_cv_struct_tms=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $gcc_cv_type_clock_t" >&5
-echo "${ECHO_T}$gcc_cv_type_clock_t" >&6
-if test $gcc_cv_type_clock_t = yes; then
+echo "$as_me:$LINENO: result: $ac_cv_struct_tms" >&5
+echo "${ECHO_T}$ac_cv_struct_tms" >&6
+if test $ac_cv_struct_tms = yes; then
cat >>confdefs.h <<\_ACEOF
-#define HAVE_CLOCK_T 1
+#define HAVE_STRUCT_TMS 1
_ACEOF
fi
-echo "$as_me:$LINENO: checking for uchar" >&5
-echo $ECHO_N "checking for uchar... $ECHO_C" >&6
-if test "${gcc_cv_type_uchar+set}" = set; then
+# use gcc_cv_* here because this doesn't match the behavior of AC_CHECK_TYPE.
+# revisit after autoconf 2.50.
+echo "$as_me:$LINENO: checking for clock_t" >&5
+echo $ECHO_N "checking for clock_t... $ECHO_C" >&6
+if test "${gcc_cv_type_clock_t+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat >conftest.$ac_ext <<_ACEOF
+
+cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
@@ -8873,8 +11959,7 @@ cat >>conftest.$ac_ext <<_ACEOF
int
main ()
{
-if ((uchar *)0) return 0;
- if (sizeof(uchar)) return 0;
+clock_t x;
;
return 0;
}
@@ -8901,21 +11986,21 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
- ac_cv_type_uchar=yes
+ gcc_cv_type_clock_t=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-ac_cv_type_uchar=no
+gcc_cv_type_clock_t=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:$LINENO: result: $gcc_cv_type_uchar" >&5
-echo "${ECHO_T}$gcc_cv_type_uchar" >&6
-if test $ac_cv_type_uchar = yes; then
+echo "$as_me:$LINENO: result: $gcc_cv_type_clock_t" >&5
+echo "${ECHO_T}$gcc_cv_type_clock_t" >&6
+if test $gcc_cv_type_clock_t = yes; then
cat >>confdefs.h <<\_ACEOF
-#define HAVE_UCHAR 1
+#define HAVE_CLOCK_T 1
_ACEOF
fi
@@ -9085,6 +12170,15 @@ if test "${with_system_libunwind+set}" = set; then
fi;
+# config.gcc also contains tests of with_system_libunwind.
+if test x$with_system_libunwind = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETIPINFO 1
+_ACEOF
+
+fi
+
# --------------------------------------------------------
# Build, host, and target specific configuration fragments
# --------------------------------------------------------
@@ -9182,6 +12276,14 @@ _ACEOF
fi
+if test x$use_long_long_for_widest_fast_int = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_LONG_LONG_FOR_WIDEST_FAST_INT 1
+_ACEOF
+
+fi
+
count=a
for f in $host_xm_file; do
count=${count}x
@@ -9215,8 +12317,69 @@ if test "$host_xm_file" != "$build_xm_file"; then
fi
fi
+case ${host} in
+ powerpc*-*-darwin*)
+ echo "$as_me:$LINENO: checking whether mcontext_t fields have underscores" >&5
+echo $ECHO_N "checking whether mcontext_t fields have underscores... $ECHO_C" >&6
+if test "${gcc_cv_mcontext_underscores+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+
+#include <sys/signal.h>
+#include <ucontext.h>
+int main() { mcontext_t m; if (m->ss.srr0) return 0; return 0; }
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ gcc_cv_mcontext_underscores=no
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+gcc_cv_mcontext_underscores=yes
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_mcontext_underscores" >&5
+echo "${ECHO_T}$gcc_cv_mcontext_underscores" >&6
+ if test $gcc_cv_mcontext_underscores = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAS_MCONTEXT_T_UNDERSCORES
+_ACEOF
+
+ fi
+ ;;
+esac
+
+# ---------
+# Threading
+# ---------
+
# Check if a valid thread package
-case ${enable_threads_flag} in
+case ${enable_threads} in
"" | no)
# No threads
target_thread_file='single'
@@ -9225,12 +12388,12 @@ case ${enable_threads_flag} in
# default
target_thread_file='single'
;;
- aix | dce | gnat | irix | posix | rtems | \
+ aix | dce | gnat | irix | posix | posix95 | rtems | \
single | solaris | vxworks | win32 )
- target_thread_file=${enable_threads_flag}
+ target_thread_file=${enable_threads}
;;
*)
- echo "${enable_threads_flag} is an unknown thread package" 1>&2
+ echo "${enable_threads} is an unknown thread package" 1>&2
exit 1
;;
esac
@@ -9241,9 +12404,24 @@ if test x${thread_file} = x; then
thread_file=${target_thread_file}
fi
+# Make gthr-default.h if we have a thread file.
+gthread_flags=
+if test $thread_file != single; then
+ rm -f gthr-default.h
+ echo "#include \"gthr-${thread_file}.h\"" > gthr-default.h
+ gthread_flags=-DHAVE_GTHR_DEFAULT
+fi
+
+
+# --------
+# UNSORTED
+# --------
+
+use_cxa_atexit=no
if test x$enable___cxa_atexit = xyes || \
test x$enable___cxa_atexit = x -a x$default_use_cxa_atexit = xyes; then
- echo "$as_me:$LINENO: checking for __cxa_atexit" >&5
+ if test x$host = x$target; then
+ echo "$as_me:$LINENO: checking for __cxa_atexit" >&5
echo $ECHO_N "checking for __cxa_atexit... $ECHO_C" >&6
if test "${ac_cv_func___cxa_atexit+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -9334,15 +12512,167 @@ fi
echo "$as_me:$LINENO: result: $ac_cv_func___cxa_atexit" >&5
echo "${ECHO_T}$ac_cv_func___cxa_atexit" >&6
if test $ac_cv_func___cxa_atexit = yes; then
+ use_cxa_atexit=yes
+else
+ echo "__cxa_atexit can't be enabled on this target"
+fi
+
+ else
+ # We can't check for __cxa_atexit when building a cross, so assume
+ # it is available
+ use_cxa_atexit=yes
+ fi
+ if test x$use_cxa_atexit = xyes; then
cat >>confdefs.h <<\_ACEOF
-#define DEFAULT_USE_CXA_ATEXIT 1
+#define DEFAULT_USE_CXA_ATEXIT 2
_ACEOF
+ fi
+fi
+
+use_getipinfo=yes
+if test x$with_system_libunwind = xyes; then
+ if test x$host = x$target; then
+ echo "$as_me:$LINENO: checking for library containing _Unwind_GetIPInfo" >&5
+echo $ECHO_N "checking for library containing _Unwind_GetIPInfo... $ECHO_C" >&6
+if test "${ac_cv_search__Unwind_GetIPInfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "__cxa_atexit can't be enabled on this target"
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search__Unwind_GetIPInfo=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _Unwind_GetIPInfo ();
+int
+main ()
+{
+_Unwind_GetIPInfo ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search__Unwind_GetIPInfo="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search__Unwind_GetIPInfo" = no; then
+ for ac_lib in unwind; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _Unwind_GetIPInfo ();
+int
+main ()
+{
+_Unwind_GetIPInfo ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search__Unwind_GetIPInfo="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search__Unwind_GetIPInfo" >&5
+echo "${ECHO_T}$ac_cv_search__Unwind_GetIPInfo" >&6
+if test "$ac_cv_search__Unwind_GetIPInfo" != no; then
+ test "$ac_cv_search__Unwind_GetIPInfo" = "none required" || LIBS="$ac_cv_search__Unwind_GetIPInfo $LIBS"
+
+else
+ use_getipinfo=no
fi
+ fi
+fi
+
+if test x$use_getipinfo = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETIPINFO 1
+_ACEOF
+
+else
+ echo "The system unwind library does not support _Unwind_GetIPInfo."
fi
# Look for a file containing extra machine modes.
@@ -9356,6 +12686,13 @@ _ACEOF
fi
+# Convert extra_options into a form suitable for Makefile use.
+extra_opt_files=
+for f in $extra_options; do
+ extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+done
+
+
# auto-host.h is the file containing items generated by autoconf and is
# the first file included by config.h.
# If host=build, it is correct to have bconfig include auto-host.h
@@ -9364,7 +12701,6 @@ fi
if test x$host = x$build
then
build_auto=auto-host.h
- FORBUILD=..
else
# We create a subdir, then run autoconf in the subdir.
# To prevent recursion we set host and build for the new
@@ -9381,6 +12717,7 @@ else
saved_CFLAGS="${CFLAGS}"
CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \
${realsrcdir}/configure \
+ --enable-languages=${enable_languages-all} \
--target=$target_alias --host=$build_alias --build=$build_alias
CFLAGS="${saved_CFLAGS}"
@@ -9390,7 +12727,6 @@ else
cd ..
rm -rf $tempdir
build_auto=auto-build.h
- FORBUILD=../${build_subdir}
fi
@@ -9400,21 +12736,12 @@ host_xm_file="auto-host.h ansidecl.h ${host_xm_file}"
build_xm_file="${build_auto} ansidecl.h ${build_xm_file}"
# We don't want ansidecl.h in target files, write code there in ISO/GNU C.
# put this back in temporarily.
-xm_file="ansidecl.h ${xm_file}"
+xm_file="auto-host.h ansidecl.h ${xm_file}"
# --------
# UNSORTED
# --------
-# Get the version trigger filename from the toplevel
-if test "${with_gcc_version_trigger+set}" = set; then
- gcc_version_trigger=$with_gcc_version_trigger
-else
- gcc_version_trigger=${srcdir}/version.c
-fi
-gcc_version_full=`grep version_string ${gcc_version_trigger} | sed -e 's/.*"\([^"]*\)".*/\1/'`
-gcc_version=`echo ${gcc_version_full} | sed -e 's/\([^ ]*\) .*/\1/'`
-
# Compile in configure arguments.
if test -f configargs.h ; then
# Being re-configured.
@@ -9443,11 +12770,6 @@ static const struct {
EOF
# Internationalization
-PACKAGE=gcc
-VERSION="$gcc_version"
-
-
-
# If we haven't got the data from the intl directory,
# assume NLS is disabled.
USE_NLS=no
@@ -9457,8 +12779,9 @@ INCINTL=
XGETTEXT=
GMSGFMT=
POSUB=
-if test -f ../intl/config.intl; then
- . ../intl/config.intl
+
+if test -f ../intl/config.intl; then
+ . ../intl/config.intl
fi
echo "$as_me:$LINENO: checking whether NLS is requested" >&5
echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6
@@ -9490,8 +12813,8 @@ echo $ECHO_N "checking for catalogs to be installed... $ECHO_C" >&6
# by the backticks, then collapsed again by the double quotes,
# leaving us with one backslash in the sed expression (right
# before the dot that mustn't act as a wildcard).
- cat=`echo $cat | sed -e "s!$srcdir/!!" -e "s!\\\\.po!.gmo!"`
- lang=`echo $cat | sed -e 's!po/!!' -e "s!\\\\.gmo!!"`
+ cat=`echo $cat | sed -e "s!$srcdir/po/!!" -e "s!\\\\.po!.gmo!"`
+ lang=`echo $cat | sed -e "s!\\\\.gmo!!"`
# The user is allowed to set LINGUAS to a list of languages to
# install catalogs for. If it's empty that means "all of them."
if test "x$LINGUAS" = x; then
@@ -9508,6 +12831,16 @@ echo $ECHO_N "checking for catalogs to be installed... $ECHO_C" >&6
LINGUAS="$XLINGUAS"
echo "$as_me:$LINENO: result: $LINGUAS" >&5
echo "${ECHO_T}$LINGUAS" >&6
+
+
+ DATADIRNAME=share
+
+ INSTOBJEXT=.mo
+
+ GENCAT=gencat
+
+ CATOBJEXT=.gmo
+
fi
# If LIBINTL contains LIBICONV, then clear LIBICONV so we don't get
@@ -9516,25 +12849,23 @@ case "$LIBINTL" in *$LIBICONV*)
LIBICONV= ;;
esac
+# Check whether --enable-secureplt or --disable-secureplt was given.
+if test "${enable_secureplt+set}" = set; then
+ enableval="$enable_secureplt"
+
+fi;
+
# Windows32 Registry support for specifying GCC installation paths.
# Check whether --enable-win32-registry or --disable-win32-registry was given.
if test "${enable_win32_registry+set}" = set; then
enableval="$enable_win32_registry"
fi;
-case $host_os in
- win32 | pe | cygwin* | mingw32* | uwin*)
-echo "$as_me:$LINENO: checking whether windows registry support is requested" >&5
-echo $ECHO_N "checking whether windows registry support is requested... $ECHO_C" >&6
-if test "x$enable_win32_registry" != xno; then
-
-cat >>confdefs.h <<\_ACEOF
-#define ENABLE_WIN32_REGISTRY 1
-_ACEOF
- echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
- echo "$as_me:$LINENO: checking for library containing RegOpenKeyExA" >&5
+case $host_os in
+ win32 | pe | cygwin* | mingw32* | uwin*)
+ if test "x$enable_win32_registry" != xno; then
+ echo "$as_me:$LINENO: checking for library containing RegOpenKeyExA" >&5
echo $ECHO_N "checking for library containing RegOpenKeyExA... $ECHO_C" >&6
if test "${ac_cv_search_RegOpenKeyExA+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -9658,41 +12989,29 @@ echo "${ECHO_T}$ac_cv_search_RegOpenKeyExA" >&6
if test "$ac_cv_search_RegOpenKeyExA" != no; then
test "$ac_cv_search_RegOpenKeyExA" = "none required" || LIBS="$ac_cv_search_RegOpenKeyExA $LIBS"
-fi
-
else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+ enable_win32_registry=no
fi
-# Check if user specified a different registry key.
-case "x${enable_win32_registry}" in
-x | xyes)
- # default.
- gcc_cv_win32_registry_key="$VERSION"
- ;;
-xno)
- # no registry lookup.
- gcc_cv_win32_registry_key=''
- ;;
-*)
- # user-specified key.
- gcc_cv_win32_registry_key="$enable_win32_registry"
- ;;
-esac
+ fi
+
+ if test "x$enable_win32_registry" != xno; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_WIN32_REGISTRY 1
+_ACEOF
-if test "x$enable_win32_registry" != xno; then
- echo "$as_me:$LINENO: checking registry key on windows hosts" >&5
-echo $ECHO_N "checking registry key on windows hosts... $ECHO_C" >&6
+
+ if test "x$enable_win32_registry" != xyes \
+ && test "x$enable_win32_registry" != x; then
cat >>confdefs.h <<_ACEOF
-#define WIN32_REGISTRY_KEY "$gcc_cv_win32_registry_key"
+#define WIN32_REGISTRY_KEY "$enable_win32_registry"
_ACEOF
- echo "$as_me:$LINENO: result: $gcc_cv_win32_registry_key" >&5
-echo "${ECHO_T}$gcc_cv_win32_registry_key" >&6
-fi
-;;
+ fi
+ fi
+ ;;
esac
# Get an absolute path to the GCC top-level source directory
@@ -9722,37 +13041,33 @@ do
done
tmake_file="${tmake_file_}"
-symbolic_link='ln -s'
-
# If the host doesn't support symlinks, modify CC in
# FLAGS_TO_PASS so CC="stage1/xgcc -Bstage1/" works.
# Otherwise, we can use "CC=$(CC)".
rm -f symtest.tem
-if $symbolic_link $srcdir/gcc.c symtest.tem 2>/dev/null
-then
- cc_set_by_configure="\$(CC)"
- quoted_cc_set_by_configure="\$(CC)"
- stage_prefix_set_by_configure="\$(STAGE_PREFIX)"
- quoted_stage_prefix_set_by_configure="\$(STAGE_PREFIX)"
-else
- rm -f symtest.tem
- if cp -p $srcdir/gcc.c symtest.tem 2>/dev/null
- then
- symbolic_link="cp -p"
- else
- symbolic_link="cp"
- fi
- cc_set_by_configure="\`case '\$(CC)' in stage*) echo '\$(CC)' | sed -e 's|stage|../stage|g';; *) echo '\$(CC)';; esac\`"
- quoted_cc_set_by_configure="\\\`case '\\\$(CC)' in stage*) echo '\\\$(CC)' | sed -e 's|stage|../stage|g';; *) echo '\\\$(CC)';; esac\\\`"
- stage_prefix_set_by_configure="\`case '\$(STAGE_PREFIX)' in stage*) echo '\$(STAGE_PREFIX)' | sed -e 's|stage|../stage|g';; *) echo '\$(STAGE_PREFIX)';; esac\`"
- quoted_stage_prefix_set_by_configure="\\\`case '\\\$(STAGE_PREFIX)' in stage*) echo '\\\$(STAGE_PREFIX)' | sed -e 's|stage|../stage|g';; *) echo '\\\$(STAGE_PREFIX)';; esac\\\`"
-fi
-rm -f symtest.tem
+case "$LN_S" in
+ *-s*)
+ cc_set_by_configure="\$(CC)"
+ quoted_cc_set_by_configure="\$(CC)"
+ stage_prefix_set_by_configure="\$(STAGE_PREFIX)"
+ quoted_stage_prefix_set_by_configure="\$(STAGE_PREFIX)"
+ ;;
+ *)
+ cc_set_by_configure="\`case '\$(CC)' in stage*) echo '\$(CC)' | sed -e 's|stage|../stage|g';; *) echo '\$(CC)';; esac\`"
+ quoted_cc_set_by_configure="\\\`case '\\\$(CC)' in stage*) echo '\\\$(CC)' | sed -e 's|stage|../stage|g';; *) echo '\\\$(CC)';; esac\\\`"
+ stage_prefix_set_by_configure="\`case '\$(STAGE_PREFIX)' in stage*) echo '\$(STAGE_PREFIX)' | sed -e 's|stage|../stage|g';; *) echo '\$(STAGE_PREFIX)';; esac\`"
+ quoted_stage_prefix_set_by_configure="\\\`case '\\\$(STAGE_PREFIX)' in stage*) echo '\\\$(STAGE_PREFIX)' | sed -e 's|stage|../stage|g';; *) echo '\\\$(STAGE_PREFIX)';; esac\\\`"
+ ;;
+esac
+
+# This is a terrible hack which will go away some day.
+host_cc_for_libada=${CC}
+
out_object_file=`basename $out_file .c`.o
-tm_file_list=
-tm_include_list=
+tm_file_list="options.h"
+tm_include_list="options.h"
for f in $tm_file; do
case $f in
defaults.h )
@@ -9841,11 +13156,21 @@ done
CROSS=
ALL=all.internal
SYSTEM_HEADER_DIR='$(NATIVE_SYSTEM_HEADER_DIR)'
+
+if test "x$with_build_sysroot" != x; then
+ build_system_header_dir=$with_build_sysroot'$(NATIVE_SYSTEM_HEADER_DIR)'
+else
+ # This value is used, even on a native system, because
+ # CROSS_SYSTEM_HEADER_DIR is just
+ # $(TARGET_SYSTEM_ROOT)$(NATIVE_SYSTEM_HEADER_DIR).
+ build_system_header_dir='$(CROSS_SYSTEM_HEADER_DIR)'
+fi
+
if test x$host != x$target
then
CROSS="-DCROSS_COMPILE"
ALL=all.cross
- SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)'
+ SYSTEM_HEADER_DIR=$build_system_header_dir
case "$host","$target" in
# Darwin crosses can use the host system's libraries and headers,
# because of the fat library support. Of course, it must be the
@@ -9867,8 +13192,7 @@ then
CROSS="$CROSS -DNATIVE_CROSS" ;;
esac
elif test "x$TARGET_SYSTEM_ROOT" != x; then
- # This is just $(TARGET_SYSTEM_ROOT)$(NATIVE_SYSTEM_HEADER_DIR)
- SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)'
+ SYSTEM_HEADER_DIR=$build_system_header_dir
fi
# If this is a cross-compiler that does not
@@ -9879,11 +13203,11 @@ fi
# then define inhibit_libc in LIBGCC2_CFLAGS.
# This prevents libgcc2 from containing any code which requires libc
# support.
-inhibit_libc=
+inhibit_libc=false
if { { test x$host != x$target && test "x$with_sysroot" = x ; } ||
test x$with_newlib = xyes ; } &&
{ test "x$with_headers" = x || test "x$with_headers" = xno ; } ; then
- inhibit_libc=-Dinhibit_libc
+ inhibit_libc=true
fi
@@ -9892,11 +13216,8 @@ fi
# Also, we cannot run fixincludes or fix-header.
# These are the normal (build=host) settings:
-BUILD_PREFIX=
-BUILD_PREFIX_1=ignore-
CC_FOR_BUILD='$(CC)'
BUILD_CFLAGS='$(ALL_CFLAGS)'
-
STMP_FIXINC=stmp-fixinc
# Possibly disable fixproto, on a per-target basis.
@@ -9913,13 +13234,12 @@ esac
# And these apply if build != host, or we are generating coverage data
if test x$build != x$host || test "x$coverage_flags" != x
then
- BUILD_PREFIX=build-
- BUILD_PREFIX_1=build-
BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)'
if test "x$TARGET_SYSTEM_ROOT" = x; then
- STMP_FIXINC=
- STMP_FIXPROTO=
+ if test "x$STMP_FIXPROTO" != x; then
+ STMP_FIXPROTO=stmp-install-fixproto
+ fi
fi
fi
@@ -9931,6 +13251,13 @@ for file in ${extra_headers} ; do
extra_headers_list="${extra_headers_list} \$(srcdir)/config/${cpu_type}/${file}"
done
+# Define collect2 in Makefile.
+case $host_can_use_collect2 in
+ no) collect2= ;;
+ *) collect2='collect2$(exeext)' ;;
+esac
+
+
# Add a definition of USE_COLLECT2 if system wants one.
case $use_collect2 in
no) use_collect2= ;;
@@ -9938,9 +13265,20 @@ case $use_collect2 in
*)
host_xm_defines="${host_xm_defines} USE_COLLECT2"
xm_defines="${xm_defines} USE_COLLECT2"
+ case $host_can_use_collect2 in
+ no)
+ { { echo "$as_me:$LINENO: error: collect2 is required but cannot be built on this system" >&5
+echo "$as_me: error: collect2 is required but cannot be built on this system" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
;;
esac
+# ---------------------------
+# Assembler & linker features
+# ---------------------------
+
# Identify the assembler which will work hand-in-glove with the newly
# built GCC, so that we can examine its features. This is the assembler
# which will be driven by the driver program.
@@ -9948,30 +13286,87 @@ esac
# If build != host, and we aren't building gas in-tree, we identify a
# build->target assembler and hope that it will have the same features
# as the host->target assembler we'll be using.
-echo "$as_me:$LINENO: checking what assembler to use" >&5
-echo $ECHO_N "checking what assembler to use... $ECHO_C" >&6
-in_tree_gas=no
-gcc_cv_as=
gcc_cv_gas_major_version=
gcc_cv_gas_minor_version=
gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gas
+
+if test "${gcc_cv_as+set}" = set; then
+ :
+else
+
if test -x "$DEFAULT_ASSEMBLER"; then
gcc_cv_as="$DEFAULT_ASSEMBLER"
-elif test -x "$AS"; then
- gcc_cv_as="$AS"
-elif test -x as$host_exeext; then
- # Build using assembler in the current directory.
- gcc_cv_as=./as$host_exeext
elif test -f $gcc_cv_as_gas_srcdir/configure.in \
- && test -f ../gas/Makefile; then
- # Single tree build which includes gas.
+ && test -f ../gas/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_as=../gas/as-new$build_exeext
+elif test -x as$build_exeext; then
+ # Build using assembler in the current directory.
+ gcc_cv_as=./as$build_exeext
+elif test -x $AS_FOR_TARGET; then
+ gcc_cv_as="$AS_FOR_TARGET"
+else
+ # Extract the first word of "$AS_FOR_TARGET", so it can be a program name with args.
+set dummy $AS_FOR_TARGET; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_gcc_cv_as+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $gcc_cv_as in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_as="$gcc_cv_as" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_as="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+gcc_cv_as=$ac_cv_path_gcc_cv_as
+
+if test -n "$gcc_cv_as"; then
+ echo "$as_me:$LINENO: result: $gcc_cv_as" >&5
+echo "${ECHO_T}$gcc_cv_as" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+fi
+
+
+ORIGINAL_AS_FOR_TARGET=$gcc_cv_as
+
+
+echo "$as_me:$LINENO: checking what assembler to use" >&5
+echo $ECHO_N "checking what assembler to use... $ECHO_C" >&6
+if test "$gcc_cv_as" = ../gas/as-new$build_exeext; then
+ # Single tree build which includes gas. We want to prefer it
+ # over whatever linker top-level may have detected, since
+ # we'll use what we're building after installation anyway.
+ echo "$as_me:$LINENO: result: newly built gas" >&5
+echo "${ECHO_T}newly built gas" >&6
in_tree_gas=yes
gcc_cv_as_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd
for f in $gcc_cv_as_bfd_srcdir/configure \
$gcc_cv_as_gas_srcdir/configure \
$gcc_cv_as_gas_srcdir/configure.in \
$gcc_cv_as_gas_srcdir/Makefile.in ; do
- gcc_cv_gas_version=`grep '^VERSION=[0-9]*\.[0-9]*' $f`
+ gcc_cv_gas_version=`sed -n -e 's/^[ ]*\(VERSION=[0-9]*\.[0-9]*.*\)/\1/p' < $f`
if test x$gcc_cv_gas_version != x; then
break
fi
@@ -9986,8 +13381,6 @@ gcc_cv_gas_vers=`expr \( \( $gcc_cv_gas_major_version \* 1000 \) \
+ $gcc_cv_gas_minor_version \) \* 1000 \
+ $gcc_cv_gas_patch_version`
- rm -f as$host_exeext
- $symbolic_link ../gas/as-new$host_exeext as$host_exeext 2>/dev/null
in_tree_gas_is_elf=no
if grep 'obj_format = elf' ../gas/Makefile > /dev/null \
|| (grep 'obj_format = multi' ../gas/Makefile \
@@ -9995,77 +13388,11 @@ gcc_cv_gas_vers=`expr \( \( $gcc_cv_gas_major_version \* 1000 \) \
then
in_tree_gas_is_elf=yes
fi
-fi
-
-if test "x$gcc_cv_as" = x; then
- # Search the same directories that the installed compiler will
- # search. Else we may find the wrong assembler and lose. If we
- # do not find a suitable assembler binary, then try the user's
- # path.
- #
- # Also note we have to check MD_EXEC_PREFIX before checking the
- # user's path. Unfortunately, there is no good way to get at the
- # value of MD_EXEC_PREFIX here. So we do a brute force search
- # through all the known MD_EXEC_PREFIX values. Ugh. This needs
- # to be fixed as part of the make/configure rewrite too.
-
- if test "x$exec_prefix" = xNONE; then
- if test "x$prefix" = xNONE; then
- test_prefix=/usr/local
- else
- test_prefix=$prefix
- fi
- else
- test_prefix=$exec_prefix
- fi
-
- # If the loop below does not find an assembler, then use whatever
- # one we can find in the users's path.
- # user's path.
- if test "x$program_prefix" != xNONE; then
- gcc_cv_as=${program_prefix}as$host_exeext
- else
- gcc_cv_as=`echo as | sed ${program_transform_name}`$host_exeext
- fi
-
- test_dirs="$test_prefix/libexec/gcc/$target_noncanonical/$gcc_version \
- $test_prefix/libexec/gcc/$target_noncanonical \
- /usr/lib/gcc/$target_noncanonical/$gcc_version \
- /usr/lib/gcc/$target_noncanonical \
- $test_prefix/$target_noncanonical/bin/$target_noncanonical/$gcc_version \
- $test_prefix/$target_noncanonical/bin"
-
- if test x$host = x$target; then
- test_dirs="$test_dirs \
- /usr/libexec \
- /usr/ccs/gcc \
- /usr/ccs/bin \
- /udk/usr/ccs/bin \
- /bsd43/usr/lib/cmplrs/cc \
- /usr/cross64/usr/bin \
- /usr/lib/cmplrs/cc \
- /sysv/usr/lib/cmplrs/cc \
- /svr4/usr/lib/cmplrs/cc \
- /usr/bin"
- fi
-
- for dir in $test_dirs; do
- if test -x $dir/as$host_exeext; then
- gcc_cv_as=$dir/as$host_exeext
- break;
- fi
- done
-fi
-case $in_tree_gas in
- yes)
- echo "$as_me:$LINENO: result: \"newly built gas\"" >&5
-echo "${ECHO_T}\"newly built gas\"" >&6
- ;;
- no)
- echo "$as_me:$LINENO: result: $gcc_cv_as" >&5
+else
+ echo "$as_me:$LINENO: result: $gcc_cv_as" >&5
echo "${ECHO_T}$gcc_cv_as" >&6
- ;;
-esac
+ in_tree_gas=no
+fi
# Identify the linker which will work hand-in-glove with the newly
# built GCC, so that we can examine its features. This is the linker
@@ -10074,166 +13401,248 @@ esac
# If build != host, and we aren't building gas in-tree, we identify a
# build->target linker and hope that it will have the same features
# as the host->target linker we'll be using.
-echo "$as_me:$LINENO: checking what linker to use" >&5
-echo $ECHO_N "checking what linker to use... $ECHO_C" >&6
-in_tree_ld=no
-gcc_cv_ld=
gcc_cv_gld_major_version=
gcc_cv_gld_minor_version=
gcc_cv_ld_gld_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/ld
gcc_cv_ld_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd
+
+if test "${gcc_cv_ld+set}" = set; then
+ :
+else
+
if test -x "$DEFAULT_LINKER"; then
gcc_cv_ld="$DEFAULT_LINKER"
-elif test -x "$LD"; then
- gcc_cv_ld="$LD"
-elif test -x collect-ld$host_exeext; then
- # Build using linker in the current directory.
- gcc_cv_ld=./collect-ld$host_exeext
elif test -f $gcc_cv_ld_gld_srcdir/configure.in \
- && test -f ../ld/Makefile; then
- # Single tree build which includes ld.
+ && test -f ../ld/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_ld=../ld/ld-new$build_exeext
+elif test -x collect-ld$build_exeext; then
+ # Build using linker in the current directory.
+ gcc_cv_ld=./collect-ld$build_exeext
+elif test -x $LD_FOR_TARGET; then
+ gcc_cv_ld="$LD_FOR_TARGET"
+else
+ # Extract the first word of "$LD_FOR_TARGET", so it can be a program name with args.
+set dummy $LD_FOR_TARGET; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_gcc_cv_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $gcc_cv_ld in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_ld="$gcc_cv_ld" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_ld="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+gcc_cv_ld=$ac_cv_path_gcc_cv_ld
+
+if test -n "$gcc_cv_ld"; then
+ echo "$as_me:$LINENO: result: $gcc_cv_ld" >&5
+echo "${ECHO_T}$gcc_cv_ld" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+fi
+
+
+ORIGINAL_LD_FOR_TARGET=$gcc_cv_ld
+
+
+echo "$as_me:$LINENO: checking what linker to use" >&5
+echo $ECHO_N "checking what linker to use... $ECHO_C" >&6
+if test "$gcc_cv_ld" = ../ld/ld-new$build_exeext; then
+ # Single tree build which includes ld. We want to prefer it
+ # over whatever linker top-level may have detected, since
+ # we'll use what we're building after installation anyway.
+ echo "$as_me:$LINENO: result: newly built ld" >&5
+echo "${ECHO_T}newly built ld" >&6
in_tree_ld=yes
in_tree_ld_is_elf=no
if (grep 'EMUL = .*elf' ../ld/Makefile \
- || grep 'EMUL = .*linux' ../ld/Makefile) > /dev/null; then
+ || grep 'EMUL = .*linux' ../ld/Makefile \
+ || grep 'EMUL = .*lynx' ../ld/Makefile) > /dev/null; then
in_tree_ld_is_elf=yes
fi
for f in $gcc_cv_ld_bfd_srcdir/configure $gcc_cv_ld_gld_srcdir/configure $gcc_cv_ld_gld_srcdir/configure.in $gcc_cv_ld_gld_srcdir/Makefile.in
do
- gcc_cv_gld_version=`grep '^VERSION=[0-9]*\.[0-9]*' $f`
+ gcc_cv_gld_version=`sed -n -e 's/^[ ]*\(VERSION=[0-9]*\.[0-9]*.*\)/\1/p' < $f`
if test x$gcc_cv_gld_version != x; then
break
fi
done
gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"`
gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"`
- rm -f collect-ld$host_exeext
- $symbolic_link ../ld/ld-new$host_exeext collect-ld$host_exeext \
- 2>/dev/null
-fi
-
-if test "x$gcc_cv_ld" = x; then
- # Search the same directories that the installed compiler will
- # search. Else we may find the wrong linker and lose. If we
- # do not find a suitable linker binary, then try the user's
- # path.
- #
- # Also note we have to check MD_EXEC_PREFIX before checking the
- # user's path. Unfortunately, there is no good way to get at the
- # value of MD_EXEC_PREFIX here. So we do a brute force search
- # through all the known MD_EXEC_PREFIX values. Ugh. This needs
- # to be fixed as part of the make/configure rewrite too.
-
- if test "x$exec_prefix" = xNONE; then
- if test "x$prefix" = xNONE; then
- test_prefix=/usr/local
- else
- test_prefix=$prefix
- fi
- else
- test_prefix=$exec_prefix
- fi
+else
+ echo "$as_me:$LINENO: result: $gcc_cv_ld" >&5
+echo "${ECHO_T}$gcc_cv_ld" >&6
+ in_tree_ld=no
+fi
- # If the loop below does not find an linker, then use whatever
- # one we can find in the users's path.
- # user's path.
- if test "x$program_prefix" != xNONE; then
- gcc_cv_ld=${program_prefix}ld$host_exeext
- else
- gcc_cv_ld=`echo ld | sed ${program_transform_name}`$host_exeext
- fi
+# Figure out what nm we will be using.
+gcc_cv_binutils_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/binutils
+if test "${gcc_cv_nm+set}" = set; then
+ :
+else
- test_dirs="$test_prefix/libexec/gcc/$target_noncanonical/$gcc_version \
- $test_prefix/libexec/gcc/$target_noncanonical \
- /usr/lib/gcc/$target_noncanonical/$gcc_version \
- /usr/lib/gcc/$target_noncanonical \
- $test_prefix/$target_noncanonical/bin/$target_noncanonical/$gcc_version \
- $test_prefix/$target_noncanonical/bin"
-
- if test x$host = x$target; then
- test_dirs="$test_dirs \
- /usr/libexec \
- /usr/ccs/gcc \
- /usr/ccs/bin \
- /udk/usr/ccs/bin \
- /bsd43/usr/lib/cmplrs/cc \
- /usr/cross64/usr/bin \
- /usr/lib/cmplrs/cc \
- /sysv/usr/lib/cmplrs/cc \
- /svr4/usr/lib/cmplrs/cc \
- /usr/bin"
- fi
+if test -f $gcc_cv_binutils_srcdir/configure.in \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_nm=../binutils/nm-new$build_exeext
+elif test -x nm$build_exeext; then
+ gcc_cv_nm=./nm$build_exeext
+elif test -x $NM_FOR_TARGET; then
+ gcc_cv_nm="$NM_FOR_TARGET"
+else
+ # Extract the first word of "$NM_FOR_TARGET", so it can be a program name with args.
+set dummy $NM_FOR_TARGET; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_gcc_cv_nm+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $gcc_cv_nm in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_nm="$gcc_cv_nm" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_nm="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
- for dir in $test_dirs; do
- if test -x $dir/ld$host_exeext; then
- gcc_cv_ld=$dir/ld$host_exeext
- break;
- fi
- done
-fi
-case $in_tree_ld in
- yes)
- echo "$as_me:$LINENO: result: \"newly built ld\"" >&5
-echo "${ECHO_T}\"newly built ld\"" >&6
- ;;
- no)
- echo "$as_me:$LINENO: result: $gcc_cv_ld" >&5
-echo "${ECHO_T}$gcc_cv_ld" >&6
- ;;
+ ;;
esac
+fi
+gcc_cv_nm=$ac_cv_path_gcc_cv_nm
+
+if test -n "$gcc_cv_nm"; then
+ echo "$as_me:$LINENO: result: $gcc_cv_nm" >&5
+echo "${ECHO_T}$gcc_cv_nm" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+fi
+
-# Figure out what nm we will be using.
-gcc_cv_binutils_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/binutils
echo "$as_me:$LINENO: checking what nm to use" >&5
echo $ECHO_N "checking what nm to use... $ECHO_C" >&6
-in_tree_nm=no
-if test -x nm$host_exeext; then
- gcc_cv_nm=./nm$host_exeext
-elif test -f $gcc_cv_binutils_srcdir/configure.in \
- && test -f ../binutils/Makefile; then
+if test "$gcc_cv_nm" = ../binutils/nm-new$build_exeext; then
# Single tree build which includes binutils.
+ echo "$as_me:$LINENO: result: newly built nm" >&5
+echo "${ECHO_T}newly built nm" >&6
in_tree_nm=yes
- gcc_cv_nm=./nm$host_exeext
- rm -f nm$host_exeext
- $symbolic_link ../binutils/nm-new$host_exeext nm$host_exeext 2>/dev/null
-elif test "x$program_prefix" != xNONE; then
- gcc_cv_nm=${program_prefix}nm$host_exeext
-else
- gcc_cv_nm=`echo nm | sed ${program_transform_name}`$host_exeext
-fi
-case $in_tree_nm in
- yes) echo "$as_me:$LINENO: result: \"newly built nm\"" >&5
-echo "${ECHO_T}\"newly built nm\"" >&6 ;;
- no) echo "$as_me:$LINENO: result: $gcc_cv_nm" >&5
-echo "${ECHO_T}$gcc_cv_nm" >&6 ;;
-esac
+else
+ echo "$as_me:$LINENO: result: $gcc_cv_nm" >&5
+echo "${ECHO_T}$gcc_cv_nm" >&6
+ in_tree_nm=no
+fi
+
+ORIGINAL_NM_FOR_TARGET=$gcc_cv_nm
+
# Figure out what objdump we will be using.
+if test "${gcc_cv_objdump+set}" = set; then
+ :
+else
+
+if test -f $gcc_cv_binutils_srcdir/configure.in \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ # Single tree build which includes binutils.
+ gcc_cv_objdump=../binutils/objdump$build_exeext
+elif test -x objdump$build_exeext; then
+ gcc_cv_objdump=./objdump$build_exeext
+elif test -x $OBJDUMP_FOR_TARGET; then
+ gcc_cv_objdump="$OBJDUMP_FOR_TARGET"
+else
+ # Extract the first word of "$OBJDUMP_FOR_TARGET", so it can be a program name with args.
+set dummy $OBJDUMP_FOR_TARGET; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_gcc_cv_objdump+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $gcc_cv_objdump in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_objdump="$gcc_cv_objdump" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_objdump="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+gcc_cv_objdump=$ac_cv_path_gcc_cv_objdump
+
+if test -n "$gcc_cv_objdump"; then
+ echo "$as_me:$LINENO: result: $gcc_cv_objdump" >&5
+echo "${ECHO_T}$gcc_cv_objdump" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+fi
+
+
echo "$as_me:$LINENO: checking what objdump to use" >&5
echo $ECHO_N "checking what objdump to use... $ECHO_C" >&6
-in_tree_objdump=no
-if test -x objdump$host_exeext; then
- gcc_cv_objdump=./objdump$host_exeext
-elif test -f $gcc_cv_binutils_srcdir/configure.in \
- && test -f ../binutils/Makefile; then
+if test "$gcc_cv_objdump" = ../binutils/objdump$build_exeext; then
# Single tree build which includes binutils.
- in_tree_objdump=yes
- gcc_cv_objdump=./objdump$host_exeext
- rm -f objdump$host_exeext
- $symbolic_link ../binutils/objdump$host_exeext \
- objdump$host_exeext 2>/dev/null
-elif test "x$program_prefix" != xNONE; then
- gcc_cv_objdump=${program_prefix}objdump$host_exeext
-else
- gcc_cv_objdump=`echo objdump | \
- sed ${program_transform_name}`$host_exeext
-fi
-case $in_tree_objdump in
- yes) echo "$as_me:$LINENO: result: \"newly built objdump\"" >&5
-echo "${ECHO_T}\"newly built objdump\"" >&6 ;;
- no) echo "$as_me:$LINENO: result: $gcc_cv_objdump" >&5
-echo "${ECHO_T}$gcc_cv_objdump" >&6 ;;
-esac
+ echo "$as_me:$LINENO: result: newly built objdump" >&5
+echo "${ECHO_T}newly built objdump" >&6
+elif test x$gcc_cv_objdump = x; then
+ echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6
+else
+ echo "$as_me:$LINENO: result: $gcc_cv_objdump" >&5
+echo "${ECHO_T}$gcc_cv_objdump" >&6
+fi
# Figure out what assembler alignment features are present.
echo "$as_me:$LINENO: checking assembler for .balign and .p2align" >&5
@@ -10397,6 +13806,43 @@ _ACEOF
fi
+echo "$as_me:$LINENO: checking assembler for .weakref" >&5
+echo $ECHO_N "checking assembler for .weakref... $ECHO_C" >&6
+if test "${gcc_cv_as_weakref+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_weakref=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 17 \) \* 1000 + 0`
+ then gcc_cv_as_weakref=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo ' .weakref foobar, barfnot' > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_weakref=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_weakref" >&5
+echo "${ECHO_T}$gcc_cv_as_weakref" >&6
+if test $gcc_cv_as_weakref = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GAS_WEAKREF 1
+_ACEOF
+
+fi
+
echo "$as_me:$LINENO: checking assembler for .nsubspa comdat" >&5
echo $ECHO_N "checking assembler for .nsubspa comdat... $ECHO_C" >&6
if test "${gcc_cv_as_nsubspa_comdat+set}" = set; then
@@ -10496,8 +13942,12 @@ else
-e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)$,\1,p' \
-e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\)[ ].*$,\1,p' \
-e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[ ].*$,\1,p' \
- -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[ ].*$,\1,p'`
+ -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[ ].*$,\1,p' \
+ -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[ -].*$,\1,p'`
ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)[-]*\([01][0-9]\)[-]*\([0-3][0-9]\).*$,\1\2\3,p'`
+ ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
+ ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
+ ld_vers_patch=`expr "$ld_vers" : '[0-9]*\.[0-9]*\.\([0-9]*\)'`
if test 0"$ld_date" -lt 20020404; then
if test -n "$ld_date"; then
# If there was date string, but was earlier than 2002-04-04, fail
@@ -10506,9 +13956,6 @@ else
# If there was no date string nor ld version number, something is wrong
gcc_cv_ld_hidden=no
else
- ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
- ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
- ld_vers_patch=`expr "$ld_vers" : '[0-9]*\.[0-9]*\.\([0-9]*\)'`
test -z "$ld_vers_patch" && ld_vers_patch=0
if test "$ld_vers_major" -lt 2; then
gcc_cv_ld_hidden=no
@@ -10535,6 +13982,7 @@ echo "$as_me:$LINENO: result: $gcc_cv_ld_hidden" >&5
echo "${ECHO_T}$gcc_cv_ld_hidden" >&6
libgcc_visibility=no
+
if test $gcc_cv_as_hidden = yes && test $gcc_cv_ld_hidden = yes; then
libgcc_visibility=yes
@@ -10667,11 +14115,14 @@ cat > conftest.big <<EOF
EOF
# If the assembler didn't choke, and we can objdump,
# and we got the correct data, then succeed.
+ # The text in the here-document typically retains its unix-style line
+ # endings, while the output of objdump will use host line endings.
+ # Therefore, use diff -b for the comparisons.
if test x$gcc_cv_objdump != x \
&& $gcc_cv_objdump -s -j .eh_frame conftest.o 2>/dev/null \
| tail -3 > conftest.got \
- && { cmp conftest.lit conftest.got > /dev/null 2>&1 \
- || cmp conftest.big conftest.got > /dev/null 2>&1; }
+ && { diff -b conftest.lit conftest.got > /dev/null 2>&1 \
+ || diff -b conftest.big conftest.got > /dev/null 2>&1; }
then
gcc_cv_as_eh_frame=yes
elif { ac_try='$gcc_cv_as -o conftest.o --traditional-format /dev/null'
@@ -10735,12 +14186,137 @@ fi
echo "$as_me:$LINENO: result: $gcc_cv_as_shf_merge" >&5
echo "${ECHO_T}$gcc_cv_as_shf_merge" >&6
+if test $gcc_cv_as_shf_merge = no; then
+ echo "$as_me:$LINENO: checking assembler for section merging support" >&5
+echo $ECHO_N "checking assembler for section merging support... $ECHO_C" >&6
+if test "${gcc_cv_as_shf_merge+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_shf_merge=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 12 \) \* 1000 + 0`
+ then gcc_cv_as_shf_merge=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo '.section .rodata.str, "aMS", %progbits, 1' > conftest.s
+ if { ac_try='$gcc_cv_as --fatal-warnings -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_shf_merge=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_shf_merge" >&5
+echo "${ECHO_T}$gcc_cv_as_shf_merge" >&6
+
+fi
cat >>confdefs.h <<_ACEOF
#define HAVE_GAS_SHF_MERGE `if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`
_ACEOF
+echo "$as_me:$LINENO: checking assembler for COMDAT group support" >&5
+echo $ECHO_N "checking assembler for COMDAT group support... $ECHO_C" >&6
+if test "${gcc_cv_as_comdat_group+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_comdat_group=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 16 \) \* 1000 + 0`
+ then gcc_cv_as_comdat_group=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo '.section .text,"axG",@progbits,.foo,comdat' > conftest.s
+ if { ac_try='$gcc_cv_as --fatal-warnings -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_comdat_group=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_comdat_group" >&5
+echo "${ECHO_T}$gcc_cv_as_comdat_group" >&6
+
+if test $gcc_cv_as_comdat_group = yes; then
+ gcc_cv_as_comdat_group_percent=no
+else
+ echo "$as_me:$LINENO: checking assembler for COMDAT group support" >&5
+echo $ECHO_N "checking assembler for COMDAT group support... $ECHO_C" >&6
+if test "${gcc_cv_as_comdat_group_percent+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_comdat_group_percent=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 16 \) \* 1000 + 0`
+ then gcc_cv_as_comdat_group_percent=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo '.section .text,"axG",%progbits,.foo,comdat' > conftest.s
+ if { ac_try='$gcc_cv_as --fatal-warnings -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_comdat_group_percent=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_comdat_group_percent" >&5
+echo "${ECHO_T}$gcc_cv_as_comdat_group_percent" >&6
+
+fi
+if test $in_tree_ld != yes && test x"$ld_vers" != x; then
+ comdat_group=yes
+ if test 0"$ld_date" -lt 20050308; then
+ if test -n "$ld_date"; then
+ # If there was date string, but was earlier than 2005-03-08, fail
+ comdat_group=no
+ elif test "$ld_vers_major" -lt 2; then
+ comdat_group=no
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 16; then
+ comdat_group=no
+ fi
+ fi
+else
+ # assume linkers other than GNU ld don't support COMDAT group
+ comdat_group=no
+fi
+if test $comdat_group = no; then
+ gcc_cv_as_comdat_group=no
+ gcc_cv_as_comdat_group_percent=no
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_COMDAT_GROUP `if test $gcc_cv_as_comdat_group = yes || test $gcc_cv_as_comdat_group_percent = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
# Thread-local storage - the check is heavily parametrized.
conftest_s=
tls_first_major=
@@ -10770,6 +14346,57 @@ foo: .long 25
tls_first_minor=13
tls_as_opt=--fatal-warnings
;;
+ frv*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+x: .long 25
+ .text
+ call #gettlsoff(x)'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+ hppa*-*-linux*)
+ conftest_s='
+t1: .reg %r20
+t2: .reg %r21
+gp: .reg %r19
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .align 4
+ addil LT%foo-$tls_gdidx$,gp
+ ldo RT%foo-$tls_gdidx$(%r1),%arg0
+ b __tls_get_addr
+ nop
+ addil LT%foo-$tls_ldidx$,gp
+ b __tls_get_addr
+ ldo RT%foo-$tls_ldidx$(%r1),%arg0
+ addil LR%foo-$tls_dtpoff$,%ret0
+ ldo RR%foo-$tls_dtpoff$(%r1),%t1
+ mfctl %cr27,%t1
+ addil LT%foo-$tls_ieoff$,gp
+ ldw RT%foo-$tls_ieoff$(%r1),%t2
+ add %t1,%t2,%t3
+ mfctl %cr27,%t1
+ addil LR%foo-$tls_leoff$,%t1
+ ldo RR%foo-$tls_leoff$(%r1),%t2'
+ tls_first_major=2
+ tls_first_minor=15
+ tls_as_opt=--fatal-warnings
+ ;;
+ arm*-*-*)
+ conftest_s='
+ .section ".tdata","awT",%progbits
+foo: .long 25
+ .text
+.word foo(gottpoff)
+.word foo(tpoff)
+.word foo(tlsgd)
+.word foo(tlsldm)
+.word foo(tlsldo)'
+ tls_first_major=2
+ tls_first_minor=17
+ ;;
i[34567]86-*-*)
conftest_s='
.section ".tdata","awT",@progbits
@@ -10823,6 +14450,23 @@ foo: data8 25
tls_first_minor=13
tls_as_opt=--fatal-warnings
;;
+ mips*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ addiu $4, $28, %tlsgd(x)
+ addiu $4, $28, %tlsldm(x)
+ lui $4, %dtprel_hi(x)
+ addiu $4, $4, %dtprel_lo(x)
+ lw $4, %gottprel(x)($28)
+ lui $4, %tprel_hi(x)
+ addiu $4, $4, %tprel_lo(x)'
+ tls_first_major=2
+ tls_first_minor=16
+ tls_as_opt='-32 --fatal-warnings'
+ ;;
powerpc-*-*)
conftest_s='
.section ".tdata","awT",@progbits
@@ -10936,6 +14580,15 @@ foo: .long 25
;;
sparc*-*-*)
case "$target" in
+ sparc*-sun-solaris2.[56789]*)
+ # TLS was introduced in the Solaris 9 4/04 release but
+ # we do not enable it by default on Solaris 9 either.
+ if test "x$enable_tls" = xyes ; then
+ on_solaris=yes
+ else
+ enable_tls=no;
+ fi
+ ;;
sparc*-sun-solaris2.*)
on_solaris=yes
;;
@@ -10997,7 +14650,12 @@ foo: .long 25
fi
;;
esac
-if test -z "$tls_first_major"; then
+set_have_as_tls=no
+if test "x$enable_tls" = xno ; then
+ : # TLS explicitly disabled.
+elif test "x$enable_tls" = xyes ; then
+ set_have_as_tls=yes # TLS explicitly enabled.
+elif test -z "$tls_first_major"; then
: # If we don't have a check, assume no support.
else
echo "$as_me:$LINENO: checking assembler for thread-local storage support" >&5
@@ -11030,16 +14688,68 @@ fi
echo "$as_me:$LINENO: result: $gcc_cv_as_tls" >&5
echo "${ECHO_T}$gcc_cv_as_tls" >&6
if test $gcc_cv_as_tls = yes; then
+ set_have_as_tls=yes
+fi
+fi
+if test $set_have_as_tls = yes ; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_AS_TLS 1
_ACEOF
fi
-fi
# Target-specific assembler checks.
+echo "$as_me:$LINENO: checking linker -Bstatic/-Bdynamic option" >&5
+echo $ECHO_N "checking linker -Bstatic/-Bdynamic option... $ECHO_C" >&6
+gcc_cv_ld_static_dynamic=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10; then
+ gcc_cv_ld_static_dynamic=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -Bstatic/-Bdynamic option
+ if $gcc_cv_ld --help 2>/dev/null | grep -- -Bstatic > /dev/null \
+ && $gcc_cv_ld --help 2>/dev/null | grep -- -Bdynamic > /dev/null; then
+ gcc_cv_ld_static_dynamic=yes
+ fi
+fi
+if test x"$gcc_cv_ld_static_dynamic" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LD_STATIC_DYNAMIC 1
+_ACEOF
+
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_ld_static_dynamic" >&5
+echo "${ECHO_T}$gcc_cv_ld_static_dynamic" >&6
+
+if test x"$demangler_in_ld" = xyes; then
+ echo "$as_me:$LINENO: checking linker --demangle support" >&5
+echo $ECHO_N "checking linker --demangle support... $ECHO_C" >&6
+ gcc_cv_ld_demangle=no
+ if test $in_tree_ld = yes; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 14 -o "$gcc_cv_gld_major_version" -gt 2; then \
+ gcc_cv_ld_demangle=yes
+ fi
+ elif test x$gcc_cv_ld != x -a x"$gnu_ld" = xyes; then
+ # Check if the GNU linker supports --demangle option
+ if $gcc_cv_ld --help 2>/dev/null | grep no-demangle > /dev/null; then
+ gcc_cv_ld_demangle=yes
+ fi
+ fi
+ if test x"$gcc_cv_ld_demangle" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LD_DEMANGLE 1
+_ACEOF
+
+ fi
+ echo "$as_me:$LINENO: result: $gcc_cv_ld_demangle" >&5
+echo "${ECHO_T}$gcc_cv_ld_demangle" >&6
+fi
+
case "$target" in
# All TARGET_ABI_OSF targets.
alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
@@ -11375,6 +15085,55 @@ fi
;;
i[34567]86-*-* | x86_64-*-*)
+ case $target_os in
+ cygwin* | pe | mingw32*)
+ # Used for DWARF 2 in PE
+ echo "$as_me:$LINENO: checking assembler for .secrel32 relocs" >&5
+echo $ECHO_N "checking assembler for .secrel32 relocs... $ECHO_C" >&6
+if test "${gcc_cv_as_ix86_pe_secrel32+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_ix86_pe_secrel32=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 15 \) \* 1000 + 91`
+ then gcc_cv_as_ix86_pe_secrel32=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo '.text
+foo: nop
+.data
+ .secrel32 foo' > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_as_ix86_pe_secrel32=yes
+ fi
+ rm -f conftest
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_ix86_pe_secrel32" >&5
+echo "${ECHO_T}$gcc_cv_as_ix86_pe_secrel32" >&6
+if test $gcc_cv_as_ix86_pe_secrel32 = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GAS_PE_SECREL32_RELOC 1
+_ACEOF
+
+fi
+ ;;
+ esac
+
echo "$as_me:$LINENO: checking assembler for filds and fists mnemonics" >&5
echo $ECHO_N "checking assembler for filds and fists mnemonics... $ECHO_C" >&6
if test "${gcc_cv_as_ix86_filds_fists+set}" = set; then
@@ -11445,6 +15204,39 @@ _ACEOF
fi
+ echo "$as_me:$LINENO: checking assembler for ffreep mnemonic" >&5
+echo $ECHO_N "checking assembler for ffreep mnemonic... $ECHO_C" >&6
+if test "${gcc_cv_as_ix86_ffreep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_ix86_ffreep=no
+ if test x$gcc_cv_as != x; then
+ echo 'ffreep %st(1)' > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_ix86_ffreep=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_ix86_ffreep" >&5
+echo "${ECHO_T}$gcc_cv_as_ix86_ffreep" >&6
+if test $gcc_cv_as_ix86_ffreep = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_AS_IX86_FFREEP 1
+_ACEOF
+
+fi
+
# This one is used unconditionally by i386.[ch]; it is to be defined
# to 1 if the feature is present, 0 otherwise.
echo "$as_me:$LINENO: checking assembler for GOTOFF in data" >&5
@@ -11533,11 +15325,45 @@ fi
powerpc*-*-*)
case $target in
- *-*-aix*) conftest_s=' .csect .text[PR]
+ *-*-aix*) conftest_s=' .machine "pwr5"
+ .csect .text[PR]
mfcr 3,128';;
- *-*-darwin*) conftest_s=' .text
+ *-*-darwin*)
+ echo "$as_me:$LINENO: checking assembler for .machine directive support" >&5
+echo $ECHO_N "checking assembler for .machine directive support... $ECHO_C" >&6
+if test "${gcc_cv_as_machine_directive+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_machine_directive=no
+ if test x$gcc_cv_as != x; then
+ echo ' .machine ppc7400' > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_machine_directive=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_machine_directive" >&5
+echo "${ECHO_T}$gcc_cv_as_machine_directive" >&6
+
+ if test x$gcc_cv_as_machine_directive != xyes; then
+ echo "*** This target requires an assembler supporting \".machine\"" >&2
+ echo you can get it from: ftp://gcc.gnu.org/pub/gcc/infrastructure/cctools-528.5.dmg >&2
+ test x$build = x$target && exit 1
+ fi
+ conftest_s=' .text
mfcr r3,128';;
- *) conftest_s=' .text
+ *) conftest_s=' .machine power4
+ .text
mfcr 3,128';;
esac
@@ -11577,6 +15403,148 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
fi
+
+ case $target in
+ *-*-aix*) conftest_s=' .machine "pwr5"
+ .csect .text[PR]
+ popcntb 3,3';;
+ *) conftest_s=' .machine power5
+ .text
+ popcntb 3,3';;
+ esac
+
+ echo "$as_me:$LINENO: checking assembler for popcntb support" >&5
+echo $ECHO_N "checking assembler for popcntb support... $ECHO_C" >&6
+if test "${gcc_cv_as_powerpc_popcntb+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_powerpc_popcntb=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 17 \) \* 1000 + 0`
+ then gcc_cv_as_powerpc_popcntb=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_powerpc_popcntb=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntb" >&5
+echo "${ECHO_T}$gcc_cv_as_powerpc_popcntb" >&6
+if test $gcc_cv_as_powerpc_popcntb = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_AS_POPCNTB 1
+_ACEOF
+
+fi
+
+ case $target in
+ *-*-aix*) conftest_s=' .machine "pwr5x"
+ .csect .text[PR]
+ frin 1,1';;
+ *) conftest_s=' .machine power5
+ .text
+ frin 1,1';;
+ esac
+
+ echo "$as_me:$LINENO: checking assembler for fp round support" >&5
+echo $ECHO_N "checking assembler for fp round support... $ECHO_C" >&6
+if test "${gcc_cv_as_powerpc_fprnd+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_powerpc_fprnd=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 17 \) \* 1000 + 0`
+ then gcc_cv_as_powerpc_fprnd=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_powerpc_fprnd=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_fprnd" >&5
+echo "${ECHO_T}$gcc_cv_as_powerpc_fprnd" >&6
+if test $gcc_cv_as_powerpc_fprnd = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_AS_FPRND 1
+_ACEOF
+
+fi
+
+ case $target in
+ *-*-aix*) conftest_s=' .csect .text[PR]
+LCF..0:
+ addis 11,30,_GLOBAL_OFFSET_TABLE_-LCF..0@ha';;
+ *-*-darwin*)
+ conftest_s=' .text
+LCF0:
+ addis r11,r30,_GLOBAL_OFFSET_TABLE_-LCF0@ha';;
+ *) conftest_s=' .text
+.LCF0:
+ addis 11,30,_GLOBAL_OFFSET_TABLE_-.LCF0@ha';;
+ esac
+
+ echo "$as_me:$LINENO: checking assembler for rel16 relocs" >&5
+echo $ECHO_N "checking assembler for rel16 relocs... $ECHO_C" >&6
+if test "${gcc_cv_as_powerpc_rel16+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_powerpc_rel16=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 17 \) \* 1000 + 0`
+ then gcc_cv_as_powerpc_rel16=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_powerpc_rel16=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_rel16" >&5
+echo "${ECHO_T}$gcc_cv_as_powerpc_rel16" >&6
+if test $gcc_cv_as_powerpc_rel16 = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_AS_REL16 1
+_ACEOF
+
+fi
;;
mips*-*-*)
@@ -11615,9 +15583,26 @@ if test $gcc_cv_as_mips_explicit_relocs = yes; then
else target_cpu_default="($target_cpu_default)|MASK_EXPLICIT_RELOCS"
fi
fi
+ ;;
+esac
+# Mips and HP-UX need the GNU assembler.
+# Linux on IA64 might be able to use the Intel assembler.
+
+case "$target" in
+ mips*-*-* | *-*-hpux* )
+ if test x$gas_flag = xyes \
+ || test x"$host" != x"$build" \
+ || test ! -x "$gcc_cv_as" \
+ || "$gcc_cv_as" -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ :
+ else
+ echo "*** This configuration requires the GNU assembler" >&2
+ exit 1
+ fi
;;
esac
+
# ??? Not all targets support dwarf2 debug_line, even within a version
# of gas. Moreover, we need to emit a valid instruction to trigger any
# info to the output file. So, as supported targets are added to gas 2.11,
@@ -11627,7 +15612,7 @@ esac
case "$target" in
i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \
| x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-* \
- | xstormy16*-*-* | cris-*-* | xtensa-*-*)
+ | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-*)
insn="nop"
;;
ia64*-*-* | s390*-*-*)
@@ -11662,8 +15647,9 @@ fi
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }
then
- # ??? This fails with non-gnu grep. Maybe use objdump?
- if grep debug_line conftest.o > /dev/null 2>&1; then
+ if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -h conftest.o 2> /dev/null \
+ | grep debug_line > /dev/null 2>&1; then
gcc_cv_as_dwarf2_debug_line=yes
fi
else
@@ -11861,6 +15847,7 @@ elif test x$gcc_cv_ld != x; then
gcc_cv_ld_eh_frame_hdr=yes
fi
fi
+
if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then
cat >>confdefs.h <<\_ACEOF
@@ -11895,63 +15882,115 @@ fi
echo "$as_me:$LINENO: result: $gcc_cv_ld_pie" >&5
echo "${ECHO_T}$gcc_cv_ld_pie" >&6
-echo "$as_me:$LINENO: checking linker -Bstatic/-Bdynamic option" >&5
-echo $ECHO_N "checking linker -Bstatic/-Bdynamic option... $ECHO_C" >&6
-gcc_cv_ld_static_dynamic=no
+# --------
+# UNSORTED
+# --------
+
+echo "$as_me:$LINENO: checking linker --as-needed support" >&5
+echo $ECHO_N "checking linker --as-needed support... $ECHO_C" >&6
+if test "${gcc_cv_ld_as_needed+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_ld_as_needed=no
if test $in_tree_ld = yes ; then
- if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10; then
- gcc_cv_ld_static_dynamic=yes
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_as_needed=yes
fi
elif test x$gcc_cv_ld != x; then
- # Check if linker supports -Bstatic/-Bdynamic option
- if $gcc_cv_ld --help 2>/dev/null | grep -- -Bstatic > /dev/null \
- && $gcc_cv_ld --help 2>/dev/null | grep -- -Bdynamic > /dev/null; then
- gcc_cv_ld_static_dynamic=yes
+ # Check if linker supports --as-needed and --no-as-needed options
+ if $gcc_cv_ld --help 2>/dev/null | grep as-needed > /dev/null; then
+ gcc_cv_ld_as_needed=yes
fi
fi
-if test x"$gcc_cv_ld_static_dynamic" = xyes; then
+
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_ld_as_needed" >&5
+echo "${ECHO_T}$gcc_cv_ld_as_needed" >&6
+if test x"$gcc_cv_ld_as_needed" = xyes; then
cat >>confdefs.h <<\_ACEOF
-#define HAVE_LD_STATIC_DYNAMIC 1
+#define HAVE_LD_AS_NEEDED 1
_ACEOF
fi
-echo "$as_me:$LINENO: result: $gcc_cv_ld_static_dynamic" >&5
-echo "${ECHO_T}$gcc_cv_ld_static_dynamic" >&6
-case "$target" in
- *-*-linux*)
- echo "$as_me:$LINENO: checking linker --as-needed support" >&5
-echo $ECHO_N "checking linker --as-needed support... $ECHO_C" >&6
-if test "${gcc_cv_ld_as_needed+set}" = set; then
+case "$target:$tm_file" in
+ powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
+ echo "$as_me:$LINENO: checking linker support for omitting dot symbols" >&5
+echo $ECHO_N "checking linker support for omitting dot symbols... $ECHO_C" >&6
+if test "${gcc_cv_ld_no_dot_syms+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
- gcc_cv_ld_as_needed=no
+ gcc_cv_ld_no_dot_syms=no
if test $in_tree_ld = yes ; then
- if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
- && test $in_tree_ld_is_elf = yes; then
- gcc_cv_ld_as_needed=yes
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_no_dot_syms=yes
fi
- elif test x$gcc_cv_ld != x; then
- # Check if linker supports --as-needed and --no-as-needed options
- if $gcc_cv_ld --help 2>/dev/null | grep as-needed > /dev/null; then
- gcc_cv_ld_as_needed=yes
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ cat > conftest1.s <<EOF
+ .text
+ bl .foo
+EOF
+ cat > conftest2.s <<EOF
+ .section ".opd","aw"
+ .align 3
+ .globl foo
+ .type foo,@function
+foo:
+ .quad .LEfoo,.TOC.@tocbase,0
+ .text
+.LEfoo:
+ blr
+ .size foo,.-.LEfoo
+EOF
+ if $gcc_cv_as -a64 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -a64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -melf64ppc -o conftest conftest1.o conftest2.o > /dev/null 2>&1; then
+ gcc_cv_ld_no_dot_syms=yes
fi
+ rm -f conftest conftest1.o conftest2.o conftest1.s conftest2.s
fi
fi
-echo "$as_me:$LINENO: result: $gcc_cv_ld_as_needed" >&5
-echo "${ECHO_T}$gcc_cv_ld_as_needed" >&6
- if test x"$gcc_cv_ld_as_needed" = xyes; then
+echo "$as_me:$LINENO: result: $gcc_cv_ld_no_dot_syms" >&5
+echo "${ECHO_T}$gcc_cv_ld_no_dot_syms" >&6
+ if test x"$gcc_cv_ld_no_dot_syms" = xyes; then
cat >>confdefs.h <<\_ACEOF
-#define HAVE_LD_AS_NEEDED 1
+#define HAVE_LD_NO_DOT_SYMS 1
_ACEOF
fi
;;
esac
+echo "$as_me:$LINENO: checking linker --sysroot support" >&5
+echo $ECHO_N "checking linker --sysroot support... $ECHO_C" >&6
+if test "${gcc_cv_ld_sysroot+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_ld_sysroot=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 ; then
+ gcc_cv_ld_sysroot=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --help 2>/dev/null | grep sysroot > /dev/null; then
+ gcc_cv_ld_sysroot=yes
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_ld_sysroot" >&5
+echo "${ECHO_T}$gcc_cv_ld_sysroot" >&6
+if test x"$gcc_cv_ld_sysroot" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LD_SYSROOT 1
+_ACEOF
+
+fi
+
if test x$with_sysroot = x && test x$host = x$target \
&& test "$prefix" != "/usr" && test "x$prefix" != "x$local_prefix" ; then
@@ -11961,142 +16000,94 @@ _ACEOF
fi
-# Figure out what language subdirectories are present.
-# Look if the user specified --enable-languages="..."; if not, use
-# the environment variable $LANGUAGES if defined. $LANGUAGES might
-# go away some day.
-# NB: embedded tabs in this IF block -- do not untabify
-if test x"${enable_languages+set}" != xset; then
- if test x"${LANGUAGES+set}" = xset; then
- enable_languages="${LANGUAGES}"
- { echo "$as_me:$LINENO: WARNING: setting LANGUAGES is deprecated, use --enable-languages instead" >&5
-echo "$as_me: WARNING: setting LANGUAGES is deprecated, use --enable-languages instead" >&2;}
-
+# Test for stack protector support in target C library.
+case "$target" in
+ *-*-linux*)
+ echo "$as_me:$LINENO: checking __stack_chk_fail in target GNU C library" >&5
+echo $ECHO_N "checking __stack_chk_fail in target GNU C library... $ECHO_C" >&6
+if test "${gcc_cv_libc_provides_ssp+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_libc_provides_ssp=no
+ if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x; then
+ if test "x$with_sysroot" = x; then
+ glibc_header_dir="${exec_prefix}/${target_noncanonical}/sys-include"
+ elif test "x$with_sysroot" = xyes; then
+ glibc_header_dir="${exec_prefix}/${target_noncanonical}/sys-root/usr/include"
else
- enable_languages=all
+ glibc_header_dir="${with_sysroot}/usr/include"
fi
-else
- if test x"${enable_languages}" = x \
- || test x"${enable_languages}" = xyes;
- then
- { { echo "$as_me:$LINENO: error: --enable-languages needs at least one language argument" >&5
-echo "$as_me: error: --enable-languages needs at least one language argument" >&2;}
- { (exit 1); exit 1; }; }
+ else
+ glibc_header_dir=/usr/include
+ fi
+ # glibc 2.4 and later provides __stack_chk_fail and
+ # either __stack_chk_guard, or TLS access to stack guard canary.
+ if test -f $glibc_header_dir/features.h \
+ && $EGREP '^[ ]*#[ ]*define[ ]+__GNU_LIBRARY__[ ]+([1-9][0-9]|[6-9])' \
+ $glibc_header_dir/features.h > /dev/null; then
+ if $EGREP '^[ ]*#[ ]*define[ ]+__GLIBC__[ ]+([1-9][0-9]|[3-9])' \
+ $glibc_header_dir/features.h > /dev/null; then
+ gcc_cv_libc_provides_ssp=yes
+ elif $EGREP '^[ ]*#[ ]*define[ ]+__GLIBC__[ ]+2' \
+ $glibc_header_dir/features.h > /dev/null \
+ && $EGREP '^[ ]*#[ ]*define[ ]+__GLIBC_MINOR__[ ]+([1-9][0-9]|[4-9])' \
+ $glibc_header_dir/features.h > /dev/null; then
+ gcc_cv_libc_provides_ssp=yes
fi
+ fi
fi
-enable_languages=`echo "${enable_languages}" | sed -e 's/[ ,][ ,]*/,/g' -e 's/,$//'`
+echo "$as_me:$LINENO: result: $gcc_cv_libc_provides_ssp" >&5
+echo "${ECHO_T}$gcc_cv_libc_provides_ssp" >&6 ;;
+ *) gcc_cv_libc_provides_ssp=no ;;
+esac
+if test x$gcc_cv_libc_provides_ssp = xyes; then
-# First scan to see if an enabled language requires some other language.
-# We assume that a given config-lang.in will list all the language
-# front ends it requires, even if some are required indirectly.
-for lang in ${srcdir}/*/config-lang.in
-do
- case $lang in
- # The odd quoting in the next line works around
- # an apparent bug in bash 1.12 on linux.
- ${srcdir}/[*]/config-lang.in)
- ;;
- *)
- lang_alias=`sed -n -e 's,^language=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^language=\([^ ]*\).*$,\1,p' $lang`
- this_lang_requires=`sed -n -e 's,^lang_requires=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^lang_requires=\([^ ]*\).*$,\1,p' $lang`
- for other in $this_lang_requires
- do
- case ,${enable_languages}, in
- *,$other,*)
- ;;
- *,all,*)
- ;;
- *,$lang_alias,*)
- enable_languages="$enable_languages,$other"
- ;;
- esac
- done
- ;;
- esac
-done
+cat >>confdefs.h <<\_ACEOF
+#define TARGET_LIBC_PROVIDES_SSP 1
+_ACEOF
-expected_languages=`echo ,${enable_languages}, | sed -e 's:,: :g' -e 's: *: :g' -e 's: *: :g' -e 's:^ ::' -e 's: $::'`
-found_languages=
-subdirs=
-for lang in ${srcdir}/*/config-lang.in
-do
- case $lang in
- # The odd quoting in the next line works around
- # an apparent bug in bash 1.12 on linux.
- ${srcdir}/[*]/config-lang.in) ;;
- *)
- lang_alias=`sed -n -e 's,^language=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^language=\([^ ]*\).*$,\1,p' $lang`
- this_lang_libs=`sed -n -e 's,^target_libs=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^target_libs=\([^ ]*\).*$,\1,p' $lang`
- build_by_default=`sed -n -e 's,^build_by_default=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^build_by_default=\([^ ]*\).*$,\1,p' $lang`
- if test "x$lang_alias" = x
- then
- echo "$lang doesn't set \$language." 1>&2
- exit 1
- fi
- case ${build_by_default},${enable_languages}, in
- *,$lang_alias,*) add_this_lang=yes ;;
- no,*) add_this_lang=no ;;
- *,all,*) add_this_lang=yes ;;
- *) add_this_lang=no ;;
- esac
- found_languages="${found_languages} ${lang_alias}"
- if test x"${add_this_lang}" = xyes; then
- case $lang in
- ${srcdir}/ada/config-lang.in)
- if test x$have_gnat = xyes ; then
- subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
- fi
- ;;
- *)
- subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
- ;;
- esac
- fi
- ;;
- esac
-done
+fi
-missing_languages=
-for expected_language in ${expected_languages} ..
-do
- if test "${expected_language}" != ..; then
- missing_language="${expected_language}"
- if test "${expected_language}" = "c" \
- || test "${expected_language}" = "all"; then
- missing_language=
- fi
- for found_language in ${found_languages} ..
- do
- if test "${found_language}" != ..; then
- if test "${expected_language}" = "${found_language}"; then
- missing_language=
- fi
- fi
- done
- if test "x${missing_language}" != x; then
- missing_languages="${missing_languages} ${missing_language}"
- fi
- fi
-done
+# Check if TFmode long double should be used by default or not.
+# Some glibc targets used DFmode long double, but with glibc 2.4
+# and later they can use TFmode.
+case "$target" in
+ powerpc*-*-*gnu* | \
+ sparc*-*-linux* | \
+ s390*-*-linux* | \
+ alpha*-*-linux*)
+
+# Check whether --with-long-double-128 or --without-long-double-128 was given.
+if test "${with_long_double_128+set}" = set; then
+ withval="$with_long_double_128"
+ gcc_cv_target_ldbl128="$with_long_double_128"
+else
+ gcc_cv_target_ldbl128=no
+ if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x; then
+ if test "x$with_sysroot" = x; then
+ glibc_header_dir="${exec_prefix}/${target_noncanonical}/sys-include"
+ elif test "x$with_sysroot" = xyes; then
+ glibc_header_dir="${exec_prefix}/${target_noncanonical}/sys-root/usr/include"
+ else
+ glibc_header_dir="${with_sysroot}/usr/include"
+ fi
+ else
+ glibc_header_dir=/usr/include
+ fi
+ grep '^[ ]*#[ ]*define[ ][ ]*__LONG_DOUBLE_MATH_OPTIONAL' \
+ $glibc_header_dir/bits/wordsize.h > /dev/null 2>&1 \
+ && gcc_cv_target_ldbl128=yes
-if test "x$missing_languages" != x; then
- { { echo "$as_me:$LINENO: error:
-The following requested languages were not found:${missing_languages}
-The following languages were available: c${found_languages}" >&5
-echo "$as_me: error:
-The following requested languages were not found:${missing_languages}
-The following languages were available: c${found_languages}" >&2;}
- { (exit 1); exit 1; }; }
-fi
+fi;
+ ;;
+esac
+if test x$gcc_cv_target_ldbl128 = xyes; then
-# Make gthr-default.h if we have a thread file.
-gthread_flags=
-if test $thread_file != single; then
- rm -f gthr-default.h
- echo "#include \"gthr-${thread_file}.h\"" > gthr-default.h
- gthread_flags=-DHAVE_GTHR_DEFAULT
-fi
+cat >>confdefs.h <<\_ACEOF
+#define TARGET_DEFAULT_LONG_DOUBLE_128 1
+_ACEOF
+fi
# Find out what GC implementation we want, or may, use.
@@ -12104,9 +16095,17 @@ fi
if test "${with_gc+set}" = set; then
withval="$with_gc"
case "$withval" in
- simple | page | zone)
+ page)
GGC=ggc-$withval
;;
+ zone)
+ GGC=ggc-$withval
+
+cat >>confdefs.h <<\_ACEOF
+#define GGC_ZONE 1
+_ACEOF
+
+ ;;
*)
{ { echo "$as_me:$LINENO: error: $withval is an invalid option to --with-gc" >&5
echo "$as_me: error: $withval is an invalid option to --with-gc" >&2;}
@@ -12153,32 +16152,24 @@ else
MAINT='#'
fi
+# --------------
+# Language hooks
+# --------------
+
# Make empty files to contain the specs and options for each language.
# Then add #include lines to for a compiler that has specs and/or options.
+subdirs=
lang_opt_files=
lang_specs_files=
lang_tree_files=
-for subdir in . $subdirs
-do
- if test -f $srcdir/$subdir/lang.opt; then
- lang_opt_files="$lang_opt_files $srcdir/$subdir/lang.opt"
- fi
- if test -f $srcdir/$subdir/lang-specs.h; then
- lang_specs_files="$lang_specs_files $srcdir/$subdir/lang-specs.h"
- fi
- if test -f $srcdir/$subdir/$subdir-tree.def; then
- lang_tree_files="$lang_tree_files $srcdir/$subdir/$subdir-tree.def"
- fi
-done
-
# These (without "all_") are set in each config-lang.in.
# `language' must be a single word so is spelled singularly.
all_languages=
all_boot_languages=
all_compilers=
all_stagestuff=
-all_outputs='Makefile fixinc/Makefile gccbug mklibgcc mkheaders'
+all_outputs='Makefile gccbug mklibgcc libada-mk'
# List of language makefile fragments.
all_lang_makefrags=
# List of language subdirectory makefiles. Deprecated.
@@ -12189,6 +16180,10 @@ all_gtfiles="$target_gtfiles"
all_gtfiles_files_langs=
all_gtfiles_files_files=
+# These are the languages that are set in --enable-languages,
+# and are available in the GCC tree.
+all_selected_languages=
+
# Add the language fragments.
# Languages are added via two mechanisms. Some information must be
# recorded in makefile variables, these are defined in config-lang.in.
@@ -12198,77 +16193,122 @@ all_gtfiles_files_files=
language_hooks="Make-hooks"
-for s in $subdirs
+for lang in ${srcdir}/*/config-lang.in
do
- language=
- boot_language=
- compilers=
- stagestuff=
- outputs=
- gtfiles=
- . ${srcdir}/$s/config-lang.in
- if test "x$language" = x
- then
- echo "${srcdir}/$s/config-lang.in doesn't set \$language." 1>&2
- exit 1
- fi
- all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$s/Make-lang.in"
- if test -f ${srcdir}/$s/Makefile.in
- then all_lang_makefiles="$s/Makefile"
- fi
- all_languages="$all_languages $language"
- if test "x$boot_language" = xyes
- then
- all_boot_languages="$all_boot_languages $language"
- fi
- all_compilers="$all_compilers $compilers"
- all_stagestuff="$all_stagestuff $stagestuff"
- all_outputs="$all_outputs $outputs"
- all_gtfiles="$all_gtfiles $gtfiles"
- for f in $gtfiles
- do
- all_gtfiles_files_langs="$all_gtfiles_files_langs ${s} "
- all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
- done
+ test "$lang" = "${srcdir}/*/config-lang.in" && continue
+
+ lang_alias=`sed -n -e 's,^language=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^language=\([^ ]*\).*$,\1,p' $lang`
+ if test "x$lang_alias" = x
+ then
+ echo "$lang doesn't set \$language." 1>&2
+ exit 1
+ fi
+ subdir="`echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
+ subdirs="$subdirs $subdir"
+ case ",$enable_languages," in
+ *,$lang_alias,*)
+ all_selected_languages="$all_selected_languages $lang_alias"
+ if test -f $srcdir/$subdir/lang-specs.h; then
+ lang_specs_files="$lang_specs_files $srcdir/$subdir/lang-specs.h"
+ fi
+ ;;
+ esac
+
+ language=
+ boot_language=
+ compilers=
+ stagestuff=
+ outputs=
+ gtfiles=
+ subdir_requires=
+ . ${srcdir}/$subdir/config-lang.in
+ if test "x$language" = x
+ then
+ echo "${srcdir}/$subdir/config-lang.in doesn't set \$language." 1>&2
+ exit 1
+ fi
+
+ ok=:
+ case ",$enable_languages," in
+ *,$lang_alias,*) ;;
+ *)
+ for i in $subdir_requires; do
+ test -f "${srcdir}/$i/config-lang.in" && continue
+ ok=false
+ break
+ done
+ ;;
+ esac
+ $ok || continue
+
+ all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$subdir/Make-lang.in"
+ if test -f $srcdir/$subdir/lang.opt; then
+ lang_opt_files="$lang_opt_files $srcdir/$subdir/lang.opt"
+ fi
+ if test -f $srcdir/$subdir/$subdir-tree.def; then
+ lang_tree_files="$lang_tree_files $srcdir/$subdir/$subdir-tree.def"
+ fi
+ if test -f ${srcdir}/$subdir/Makefile.in
+ then all_lang_makefiles="$subdir/Makefile"
+ fi
+ all_languages="$all_languages $language"
+ if test "x$boot_language" = xyes
+ then
+ all_boot_languages="$all_boot_languages $language"
+ fi
+ all_compilers="$all_compilers $compilers"
+ all_stagestuff="$all_stagestuff $stagestuff"
+ all_outputs="$all_outputs $outputs"
+ all_gtfiles="$all_gtfiles $gtfiles"
+ for f in $gtfiles
+ do
+ all_gtfiles_files_langs="$all_gtfiles_files_langs ${subdir} "
+ all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
+ done
done
# Pick up gtfiles for c
gtfiles=
-s="c"
+subdir="c"
. ${srcdir}/c-config-lang.in
all_gtfiles="$all_gtfiles $gtfiles"
for f in $gtfiles
do
- all_gtfiles_files_langs="$all_gtfiles_files_langs ${s} "
+ all_gtfiles_files_langs="$all_gtfiles_files_langs ${subdir} "
all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
done
check_languages=
-for language in $all_languages
+for language in $all_selected_languages
do
- check_languages="$check_languages check-$language"
+ check_languages="$check_languages check-$language"
done
# We link each language in with a set of hooks, reached indirectly via
-# lang.${target}.
+# lang.${target}. Only do so for selected languages.
rm -f Make-hooks
touch Make-hooks
-target_list="all.build all.cross start.encap rest.encap tags \
- install-normal install-common install-man \
+target_list="all.cross start.encap rest.encap tags \
+ install-common install-man install-info dvi pdf html \
uninstall info man srcextra srcman srcinfo \
mostlyclean clean distclean maintainer-clean \
stage1 stage2 stage3 stage4 stageprofile stagefeedback"
+
for t in $target_list
do
x=
- for lang in $all_languages
+ for lang in $all_selected_languages
do
- x="$x $lang.$t"
+ x="$x $lang.$t"
done
echo "lang.$t: $x" >> Make-hooks
done
+# --------
+# UNSORTED
+# --------
+
# Create .gdbinit.
echo "dir ." > .gdbinit
@@ -12349,18 +16389,37 @@ fi;
objdir=`${PWDCMD-pwd}`
-# Substitute configuration variables
-
-
+# Check whether --with-datarootdir or --without-datarootdir was given.
+if test "${with_datarootdir+set}" = set; then
+ withval="$with_datarootdir"
+ datarootdir="\${prefix}/$with_datarootdir"
+else
+ datarootdir='$(prefix)/share'
+fi;
+# Check whether --with-docdir or --without-docdir was given.
+if test "${with_docdir+set}" = set; then
+ withval="$with_docdir"
+ docdir="\${prefix}/$with_docdir"
+else
+ docdir='$(datarootdir)'
+fi;
+# Check whether --with-htmldir or --without-htmldir was given.
+if test "${with_htmldir+set}" = set; then
+ withval="$with_htmldir"
+ htmldir="\${prefix}/$with_htmldir"
+else
+ htmldir='$(docdir)'
+fi;
+# Substitute configuration variables
@@ -12420,27 +16479,9 @@ objdir=`${PWDCMD-pwd}`
-if test x"$SET_GCC_LIB_PATH_CMD" != x; then
- # SET_GCC_LIB_PATH_CMD is "XXX=path; export XXX;". It is expanded to
- #
- # eval "set_gcc_lib_path=XXX=path; export XXX;"
- #
- eval "set_gcc_lib_path=$SET_GCC_LIB_PATH_CMD"
- # It will set set_gcc_lib_path to "export XXX=path" for GNU make.
- set_gcc_lib_path="export $set_gcc_lib_path"
-else
- set_gcc_lib_path=
-fi
-# If it doesn't already exist, create document directory
-echo "checking for the document directory." 1>&2
-if test -d doc ; then
- true
-else
- mkdir doc
-fi
# Echo link setup.
if test x${build} = x${host} ; then
@@ -12460,6 +16501,9 @@ else
fi
fi
+
+
+
# Configure the subdirectories
# AC_CONFIG_SUBDIRS($subdirs)
@@ -12994,8 +17038,6 @@ cat >>$CONFIG_STATUS <<_ACEOF
#
subdirs='$subdirs'
-symbolic_link='$symbolic_link'
-
_ACEOF
@@ -13106,6 +17148,8 @@ s,@target@,$target,;t t
s,@target_cpu@,$target_cpu,;t t
s,@target_vendor@,$target_vendor,;t t
s,@target_os@,$target_os,;t t
+s,@target_noncanonical@,$target_noncanonical,;t t
+s,@build_libsubdir@,$build_libsubdir,;t t
s,@build_subdir@,$build_subdir,;t t
s,@host_subdir@,$host_subdir,;t t
s,@target_subdir@,$target_subdir,;t t
@@ -13120,29 +17164,34 @@ s,@OBJEXT@,$OBJEXT,;t t
s,@NO_MINUS_C_MINUS_O@,$NO_MINUS_C_MINUS_O,;t t
s,@OUTPUT_OPTION@,$OUTPUT_OPTION,;t t
s,@CPP@,$CPP,;t t
-s,@GNATBIND@,$GNATBIND,;t t
-s,@ac_ct_GNATBIND@,$ac_ct_GNATBIND,;t t
+s,@EGREP@,$EGREP,;t t
s,@strict1_warn@,$strict1_warn,;t t
+s,@cxx_compat_warn@,$cxx_compat_warn,;t t
s,@warn_cflags@,$warn_cflags,;t t
s,@WERROR@,$WERROR,;t t
s,@nocommon_flag@,$nocommon_flag,;t t
-s,@EGREP@,$EGREP,;t t
+s,@TREEBROWSER@,$TREEBROWSER,;t t
s,@valgrind_path@,$valgrind_path,;t t
s,@valgrind_path_defines@,$valgrind_path_defines,;t t
s,@valgrind_command@,$valgrind_command,;t t
s,@coverage_flags@,$coverage_flags,;t t
s,@enable_multilib@,$enable_multilib,;t t
+s,@enable_decimal_float@,$enable_decimal_float,;t t
s,@enable_shared@,$enable_shared,;t t
s,@TARGET_SYSTEM_ROOT@,$TARGET_SYSTEM_ROOT,;t t
s,@TARGET_SYSTEM_ROOT_DEFINE@,$TARGET_SYSTEM_ROOT_DEFINE,;t t
s,@CROSS_SYSTEM_HEADER_DIR@,$CROSS_SYSTEM_HEADER_DIR,;t t
s,@onestep@,$onestep,;t t
+s,@datarootdir@,$datarootdir,;t t
+s,@docdir@,$docdir,;t t
+s,@htmldir@,$htmldir,;t t
s,@SET_MAKE@,$SET_MAKE,;t t
s,@AWK@,$AWK,;t t
-s,@LN@,$LN,;t t
s,@LN_S@,$LN_S,;t t
+s,@LN@,$LN,;t t
s,@RANLIB@,$RANLIB,;t t
s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@ranlib_flags@,$ranlib_flags,;t t
s,@INSTALL@,$INSTALL,;t t
s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
s,@INSTALL_DATA@,$INSTALL_DATA,;t t
@@ -13153,19 +17202,21 @@ s,@BUILD_INFO@,$BUILD_INFO,;t t
s,@GENERATED_MANPAGES@,$GENERATED_MANPAGES,;t t
s,@FLEX@,$FLEX,;t t
s,@BISON@,$BISON,;t t
+s,@NM@,$NM,;t t
+s,@AR@,$AR,;t t
s,@stage1_cflags@,$stage1_cflags,;t t
s,@COLLECT2_LIBS@,$COLLECT2_LIBS,;t t
s,@GNAT_LIBEXC@,$GNAT_LIBEXC,;t t
s,@LDEXP_LIB@,$LDEXP_LIB,;t t
s,@TARGET_GETGROUPS_T@,$TARGET_GETGROUPS_T,;t t
s,@LIBICONV@,$LIBICONV,;t t
+s,@LTLIBICONV@,$LTLIBICONV,;t t
s,@LIBICONV_DEP@,$LIBICONV_DEP,;t t
s,@manext@,$manext,;t t
s,@objext@,$objext,;t t
+s,@gthread_flags@,$gthread_flags,;t t
s,@extra_modes_file@,$extra_modes_file,;t t
-s,@FORBUILD@,$FORBUILD,;t t
-s,@PACKAGE@,$PACKAGE,;t t
-s,@VERSION@,$VERSION,;t t
+s,@extra_opt_files@,$extra_opt_files,;t t
s,@USE_NLS@,$USE_NLS,;t t
s,@LIBINTL@,$LIBINTL,;t t
s,@LIBINTL_DEP@,$LIBINTL_DEP,;t t
@@ -13174,18 +17225,28 @@ s,@XGETTEXT@,$XGETTEXT,;t t
s,@GMSGFMT@,$GMSGFMT,;t t
s,@POSUB@,$POSUB,;t t
s,@CATALOGS@,$CATALOGS,;t t
+s,@DATADIRNAME@,$DATADIRNAME,;t t
+s,@INSTOBJEXT@,$INSTOBJEXT,;t t
+s,@GENCAT@,$GENCAT,;t t
+s,@CATOBJEXT@,$CATOBJEXT,;t t
+s,@host_cc_for_libada@,$host_cc_for_libada,;t t
s,@CROSS@,$CROSS,;t t
s,@ALL@,$ALL,;t t
s,@SYSTEM_HEADER_DIR@,$SYSTEM_HEADER_DIR,;t t
s,@inhibit_libc@,$inhibit_libc,;t t
-s,@BUILD_PREFIX@,$BUILD_PREFIX,;t t
-s,@BUILD_PREFIX_1@,$BUILD_PREFIX_1,;t t
s,@CC_FOR_BUILD@,$CC_FOR_BUILD,;t t
s,@BUILD_CFLAGS@,$BUILD_CFLAGS,;t t
s,@STMP_FIXINC@,$STMP_FIXINC,;t t
s,@STMP_FIXPROTO@,$STMP_FIXPROTO,;t t
+s,@collect2@,$collect2,;t t
+s,@gcc_cv_as@,$gcc_cv_as,;t t
+s,@ORIGINAL_AS_FOR_TARGET@,$ORIGINAL_AS_FOR_TARGET,;t t
+s,@gcc_cv_ld@,$gcc_cv_ld,;t t
+s,@ORIGINAL_LD_FOR_TARGET@,$ORIGINAL_LD_FOR_TARGET,;t t
+s,@gcc_cv_nm@,$gcc_cv_nm,;t t
+s,@ORIGINAL_NM_FOR_TARGET@,$ORIGINAL_NM_FOR_TARGET,;t t
+s,@gcc_cv_objdump@,$gcc_cv_objdump,;t t
s,@libgcc_visibility@,$libgcc_visibility,;t t
-s,@gthread_flags@,$gthread_flags,;t t
s,@GGC@,$GGC,;t t
s,@zlibdir@,$zlibdir,;t t
s,@zlibinc@,$zlibinc,;t t
@@ -13204,6 +17265,7 @@ s,@all_gtfiles_files_files@,$all_gtfiles_files_files,;t t
s,@all_lang_makefrags@,$all_lang_makefrags,;t t
s,@all_lang_makefiles@,$all_lang_makefiles,;t t
s,@all_languages@,$all_languages,;t t
+s,@all_selected_languages@,$all_selected_languages,;t t
s,@all_stagestuff@,$all_stagestuff,;t t
s,@build_exeext@,$build_exeext,;t t
s,@build_install_headers_dir@,$build_install_headers_dir,;t t
@@ -13225,10 +17287,6 @@ s,@extra_programs@,$extra_programs,;t t
s,@float_h_file@,$float_h_file,;t t
s,@gcc_config_arguments@,$gcc_config_arguments,;t t
s,@gcc_gxx_include_dir@,$gcc_gxx_include_dir,;t t
-s,@libstdcxx_incdir@,$libstdcxx_incdir,;t t
-s,@gcc_version@,$gcc_version,;t t
-s,@gcc_version_full@,$gcc_version_full,;t t
-s,@gcc_version_trigger@,$gcc_version_trigger,;t t
s,@host_exeext@,$host_exeext,;t t
s,@host_xm_file_list@,$host_xm_file_list,;t t
s,@host_xm_include_list@,$host_xm_include_list,;t t
@@ -13245,7 +17303,6 @@ s,@out_file@,$out_file,;t t
s,@out_object_file@,$out_object_file,;t t
s,@stage_prefix_set_by_configure@,$stage_prefix_set_by_configure,;t t
s,@quoted_stage_prefix_set_by_configure@,$quoted_stage_prefix_set_by_configure,;t t
-s,@symbolic_link@,$symbolic_link,;t t
s,@thread_file@,$thread_file,;t t
s,@tm_file_list@,$tm_file_list,;t t
s,@tm_include_list@,$tm_include_list,;t t
@@ -13255,11 +17312,11 @@ s,@tm_p_include_list@,$tm_p_include_list,;t t
s,@xm_file_list@,$xm_file_list,;t t
s,@xm_include_list@,$xm_include_list,;t t
s,@xm_defines@,$xm_defines,;t t
-s,@target_noncanonical@,$target_noncanonical,;t t
s,@c_target_objs@,$c_target_objs,;t t
s,@cxx_target_objs@,$cxx_target_objs,;t t
s,@target_cpu_default@,$target_cpu_default,;t t
-s,@set_gcc_lib_path@,$set_gcc_lib_path,;t t
+s,@GMPLIBS@,$GMPLIBS,;t t
+s,@GMPINC@,$GMPINC,;t t
s,@LIBOBJS@,$LIBOBJS,;t t
s,@LTLIBOBJS@,$LTLIBOBJS,;t t
/@language_hooks@/r $language_hooks
@@ -13840,7 +17897,7 @@ case ${CONFIG_HEADERS} in
echo > cstamp-h ;;
esac
# Make sure all the subdirs exist.
-for d in $subdirs
+for d in $subdirs doc build
do
test -d $d || mkdir $d
done
@@ -13850,18 +17907,20 @@ done
# FLAGS_TO_PASS has been modified to solve the problem there.
# This is virtually a duplicate of what happens in configure.lang; we do
# an extra check to make sure this only happens if ln -s can be used.
-if test "$symbolic_link" = "ln -s"; then
- for d in ${subdirs} fixinc ; do
+case "$LN_S" in
+ *-s*)
+ for d in ${subdirs} ; do
STARTDIR=`${PWDCMD-pwd}`
cd $d
for t in stage1 stage2 stage3 stage4 stageprofile stagefeedback include
do
rm -f $t
- $symbolic_link ../$t $t 2>/dev/null
+ $LN_S ../$t $t 2>/dev/null
done
cd $STARTDIR
- done
-else true ; fi
+ done
+ ;;
+esac
;;
esac
done
diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c
index 451993e..c3d71bc 100644
--- a/contrib/gcc/cp/decl.c
+++ b/contrib/gcc/cp/decl.c
@@ -1,6 +1,6 @@
/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Process declarations and symbol lookup for C++ front end.
@@ -39,7 +39,6 @@ Boston, MA 02111-1307, USA. */
#include "cp-tree.h"
#include "tree-inline.h"
#include "decl.h"
-#include "lex.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
@@ -51,8 +50,9 @@ Boston, MA 02111-1307, USA. */
#include "diagnostic.h"
#include "debug.h"
#include "timevar.h"
+#include "tree-flow.h"
-static tree grokparms (tree, tree *);
+static tree grokparms (cp_parameter_declarator *, tree *);
static const char *redeclaration_error_message (tree, tree);
static int decl_jump_unsafe (tree);
@@ -61,13 +61,12 @@ static int ambi_op_p (enum tree_code);
static int unary_op_p (enum tree_code);
static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, tree *);
-static tree grokfndecl (tree, tree, tree, tree, tree, int,
- enum overload_flags, tree,
- tree, int, int, int, int, int, int, tree);
-static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree);
+static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
+ int, int, tree);
static void record_unknown_type (tree, const char *);
-static tree builtin_function_1 (const char *, tree, tree, int,
- enum built_in_class, const char *,
+static tree builtin_function_1 (const char *, tree, tree,
+ enum built_in_function code,
+ enum built_in_class cl, const char *,
tree);
static tree build_library_fn_1 (tree, enum tree_code, tree);
static int member_function_or_else (tree, tree, enum overload_flags);
@@ -78,19 +77,9 @@ static hashval_t typename_hash (const void *);
static int typename_compare (const void *, const void *);
static tree local_variable_p_walkfn (tree *, int *, void *);
static tree record_builtin_java_type (const char *, int);
-static const char *tag_name (enum tag_types code);
+static const char *tag_name (enum tag_types);
+static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
-static int walk_globals_r (tree, void*);
-static int walk_vtables_r (tree, void*);
-static tree make_label_decl (tree, int);
-static void use_label (tree);
-static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
- const location_t *);
-static void check_previous_goto (struct named_label_use_list *);
-static void check_switch_goto (struct cp_binding_level *);
-static void check_previous_gotos (tree);
-static void pop_label (tree, tree);
-static void pop_labels (tree);
static void maybe_deduce_size_from_array_init (tree, tree);
static void layout_var_decl (tree);
static void maybe_commonize_var (tree);
@@ -98,7 +87,6 @@ static tree check_initializer (tree, tree, int, tree *);
static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
static void save_function_data (tree);
static void check_function_type (tree, tree);
-static void begin_constructor_body (void);
static void finish_constructor_body (void);
static void begin_destructor_body (void);
static void finish_destructor_body (void);
@@ -109,21 +97,14 @@ static tree start_cleanup_fn (void);
static void end_cleanup_fn (void);
static tree cp_make_fname_decl (tree, int);
static void initialize_predefined_identifiers (void);
-static tree check_special_function_return_type
+static tree check_special_function_return_type
(special_function_kind, tree, tree);
static tree push_cp_library_fn (enum tree_code, tree);
static tree build_cp_library_fn (tree, enum tree_code, tree);
static void store_parm_decls (tree);
-static int cp_missing_noreturn_ok_p (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
-static tree reshape_init (tree, tree *);
-static bool reshape_init_array (tree, tree, tree *, tree);
-static tree build_typename_type (tree, tree, tree);
-
-/* Erroneous argument lists can use this *IFF* they do not modify it. */
-tree error_mark_list;
/* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
@@ -134,12 +115,6 @@ tree error_mark_list;
tree vtable_entry_type;
tree delta_type_node;
tree __t_desc_type_node;
- tree ti_desc_type_node;
- tree bltn_desc_type_node, ptr_desc_type_node;
- tree ary_desc_type_node, func_desc_type_node, enum_desc_type_node;
- tree class_desc_type_node, si_class_desc_type_node, vmi_class_desc_type_node;
- tree ptm_desc_type_node;
- tree base_desc_type_node;
tree class_type_node;
tree unknown_type_node;
@@ -166,9 +141,7 @@ tree error_mark_list;
Used by RTTI
tree type_info_type_node, tinfo_decl_id, tinfo_decl_type;
- tree tinfo_var_id;
-
-*/
+ tree tinfo_var_id; */
tree cp_global_trees[CPTI_MAX];
@@ -180,20 +153,6 @@ tree global_type_node;
/* The node that holds the "name" of the global scope. */
tree global_scope_name;
-/* Used only for jumps to as-yet undefined labels, since jumps to
- defined labels can have their validity checked immediately. */
-
-struct named_label_use_list GTY(())
-{
- struct cp_binding_level *binding_level;
- tree names_in_scope;
- tree label_decl;
- location_t o_goto_locus;
- struct named_label_use_list *next;
-};
-
-#define named_label_uses cp_function_chain->x_named_label_uses
-
#define local_names cp_function_chain->x_local_names
/* A list of objects which have constructors or destructors
@@ -208,20 +167,58 @@ tree static_aggregates;
tree integer_two_node, integer_three_node;
+/* Used only for jumps to as-yet undefined labels, since jumps to
+ defined labels can have their validity checked immediately. */
+
+struct named_label_use_entry GTY(())
+{
+ struct named_label_use_entry *next;
+ /* The binding level to which this entry is *currently* attached.
+ This is initially the binding level in which the goto appeared,
+ but is modified as scopes are closed. */
+ struct cp_binding_level *binding_level;
+ /* The head of the names list that was current when the goto appeared,
+ or the inner scope popped. These are the decls that will *not* be
+ skipped when jumping to the label. */
+ tree names_in_scope;
+ /* The location of the goto, for error reporting. */
+ location_t o_goto_locus;
+ /* True if an OpenMP structured block scope has been closed since
+ the goto appeared. This means that the branch from the label will
+ illegally exit an OpenMP scope. */
+ bool in_omp_scope;
+};
+
/* A list of all LABEL_DECLs in the function that have names. Here so
we can clear out their names' definitions at the end of the
function, and so we can check the validity of jumps to these labels. */
-struct named_label_list GTY(())
+struct named_label_entry GTY(())
{
+ /* The decl itself. */
+ tree label_decl;
+
+ /* The binding level to which the label is *currently* attached.
+ This is initially set to the binding level in which the label
+ is defined, but is modified as scopes are closed. */
struct cp_binding_level *binding_level;
+ /* The head of the names list that was current when the label was
+ defined, or the inner scope popped. These are the decls that will
+ be skipped when jumping to the label. */
tree names_in_scope;
- tree old_value;
- tree label_decl;
+ /* A tree list of all decls from all binding levels that would be
+ crossed by a backward branch to the label. */
tree bad_decls;
- struct named_label_list *next;
- unsigned int in_try_scope : 1;
- unsigned int in_catch_scope : 1;
+
+ /* A list of uses of the label, before the label is defined. */
+ struct named_label_use_entry *uses;
+
+ /* The following bits are set after the label is defined, and are
+ updated as scopes are popped. They indicate that a backward jump
+ to the label will illegally enter a scope of the given flavor. */
+ bool in_try_scope;
+ bool in_catch_scope;
+ bool in_omp_scope;
};
#define named_labels cp_function_chain->x_named_labels
@@ -235,7 +232,7 @@ int function_depth;
with __attribute__((deprecated)). An object declared as
__attribute__((deprecated)) suppresses warnings of uses of other
deprecated items. */
-
+
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
@@ -243,15 +240,6 @@ enum deprecated_states {
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
-/* Set by add_implicitly_declared_members() to keep those members from
- being flagged as deprecated or reported as using deprecated
- types. */
-int adding_implicit_members = 0;
-
-/* True if a declaration with an `extern' linkage specifier is being
- processed. */
-bool have_extern_spec;
-
/* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or
UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the
@@ -272,8 +260,8 @@ current_tmpl_spec_kind (int n_class_scopes)
struct cp_binding_level *b;
/* Scan through the template parameter scopes. */
- for (b = current_binding_level;
- b->kind == sk_template_parms;
+ for (b = current_binding_level;
+ b->kind == sk_template_parms;
b = b->level_chain)
{
/* If we see a specialization scope inside a parameter scope,
@@ -317,7 +305,7 @@ current_tmpl_spec_kind (int n_class_scopes)
/* We've not seen enough template headers to match all the
specialized classes present. For example:
- template <class T> void R<T>::S<T>::f(int);
+ template <class T> void R<T>::S<T>::f(int);
This is invalid; there needs to be one set of template
parameters for each class. */
@@ -326,7 +314,7 @@ current_tmpl_spec_kind (int n_class_scopes)
/* We're processing a non-template declaration (even though it may
be a member of a template class.) For example:
- template <class T> void S<T>::f(int);
+ template <class T> void S<T>::f(int);
The `class T' maches the `S<T>', leaving no template headers
corresponding to the `f'. */
@@ -334,14 +322,14 @@ current_tmpl_spec_kind (int n_class_scopes)
else if (n_template_parm_scopes > n_class_scopes + 1)
/* We've got too many template headers. For example:
- template <> template <class T> void f (T);
+ template <> template <class T> void f (T);
There need to be more enclosing classes. */
return tsk_excessive_parms;
else
/* This must be a template. It's of the form:
- template <class T> template <class U> void S<T>::f(U);
+ template <class T> template <class U> void S<T>::f(U);
This is a specialization if the innermost level was a
specialization; otherwise it's just a definition of the
@@ -369,14 +357,18 @@ pop_label (tree label, tree old_value)
{
location_t location;
- cp_error_at ("label `%D' used but not defined", label);
- location.file = input_filename;
+ error ("label %q+D used but not defined", label);
+#ifdef USE_MAPPED_LOCATION
+ location = input_location; /* FIXME want (input_filename, (line)0) */
+#else
+ location.file = input_filename;
location.line = 0;
+#endif
/* Avoid crashing later. */
define_label (location, DECL_NAME (label));
}
- else if (warn_unused_label && !TREE_USED (label))
- cp_warning_at ("label `%D' defined but not used", label);
+ else if (!TREE_USED (label))
+ warning (OPT_Wunused_label, "label %q+D defined but not used", label);
}
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
@@ -386,23 +378,133 @@ pop_label (tree label, tree old_value)
go out of scope. BLOCK is the top-level block for the
function. */
+static int
+pop_labels_1 (void **slot, void *data)
+{
+ struct named_label_entry *ent = (struct named_label_entry *) *slot;
+ tree block = (tree) data;
+
+ pop_label (ent->label_decl, NULL_TREE);
+
+ /* Put the labels into the "variables" of the top-level block,
+ so debugger can see them. */
+ TREE_CHAIN (ent->label_decl) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = ent->label_decl;
+
+ htab_clear_slot (named_labels, slot);
+
+ return 1;
+}
+
static void
pop_labels (tree block)
{
- struct named_label_list *link;
+ if (named_labels)
+ {
+ htab_traverse (named_labels, pop_labels_1, block);
+ named_labels = NULL;
+ }
+}
+
+/* At the end of a block with local labels, restore the outer definition. */
+
+static void
+pop_local_label (tree label, tree old_value)
+{
+ struct named_label_entry dummy;
+ void **slot;
+
+ pop_label (label, old_value);
- /* Clear out the definitions of all label names, since their scopes
- end here. */
- for (link = named_labels; link; link = link->next)
+ dummy.label_decl = label;
+ slot = htab_find_slot (named_labels, &dummy, NO_INSERT);
+ htab_clear_slot (named_labels, slot);
+}
+
+/* The following two routines are used to interface to Objective-C++.
+ The binding level is purposely treated as an opaque type. */
+
+void *
+objc_get_current_scope (void)
+{
+ return current_binding_level;
+}
+
+/* The following routine is used by the NeXT-style SJLJ exceptions;
+ variables get marked 'volatile' so as to not be clobbered by
+ _setjmp()/_longjmp() calls. All variables in the current scope,
+ as well as parent scopes up to (but not including) ENCLOSING_BLK
+ shall be thusly marked. */
+
+void
+objc_mark_locals_volatile (void *enclosing_blk)
+{
+ struct cp_binding_level *scope;
+
+ for (scope = current_binding_level;
+ scope && scope != enclosing_blk;
+ scope = scope->level_chain)
{
- pop_label (link->label_decl, link->old_value);
- /* Put the labels into the "variables" of the top-level block,
- so debugger can see them. */
- TREE_CHAIN (link->label_decl) = BLOCK_VARS (block);
- BLOCK_VARS (block) = link->label_decl;
+ tree decl;
+
+ for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
+ objc_volatilize_decl (decl);
+
+ /* Do not climb up past the current function. */
+ if (scope->kind == sk_function_parms)
+ break;
+ }
+}
+
+/* Update data for defined and undefined labels when leaving a scope. */
+
+static int
+poplevel_named_label_1 (void **slot, void *data)
+{
+ struct named_label_entry *ent = (struct named_label_entry *) *slot;
+ struct cp_binding_level *bl = (struct cp_binding_level *) data;
+ struct cp_binding_level *obl = bl->level_chain;
+
+ if (ent->binding_level == bl)
+ {
+ tree decl;
+
+ for (decl = ent->names_in_scope; decl; decl = TREE_CHAIN (decl))
+ if (decl_jump_unsafe (decl))
+ ent->bad_decls = tree_cons (NULL, decl, ent->bad_decls);
+
+ ent->binding_level = obl;
+ ent->names_in_scope = obl->names;
+ switch (bl->kind)
+ {
+ case sk_try:
+ ent->in_try_scope = true;
+ break;
+ case sk_catch:
+ ent->in_catch_scope = true;
+ break;
+ case sk_omp:
+ ent->in_omp_scope = true;
+ break;
+ default:
+ break;
+ }
}
+ else if (ent->uses)
+ {
+ struct named_label_use_entry *use;
- named_labels = NULL;
+ for (use = ent->uses; use ; use = use->next)
+ if (use->binding_level == bl)
+ {
+ use->binding_level = obl;
+ use->names_in_scope = obl->names;
+ if (bl->kind == sk_omp)
+ use->in_omp_scope = true;
+ }
+ }
+
+ return 1;
}
/* Exit a binding level.
@@ -430,65 +532,38 @@ poplevel (int keep, int reverse, int functionbody)
int tmp = functionbody;
int real_functionbody;
tree subblocks;
- tree block = NULL_TREE;
+ tree block;
tree decl;
int leaving_for_scope;
scope_kind kind;
timevar_push (TV_NAME_LOOKUP);
+ restart:
- my_friendly_assert (current_binding_level->kind != sk_class, 19990916);
+ block = NULL_TREE;
+
+ gcc_assert (current_binding_level->kind != sk_class);
real_functionbody = (current_binding_level->kind == sk_cleanup
? ((functionbody = 0), tmp) : functionbody);
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
- my_friendly_assert (!current_binding_level->class_shadowed,
- 19990414);
+ gcc_assert (!VEC_length(cp_class_binding,
+ current_binding_level->class_shadowed));
/* We used to use KEEP == 2 to indicate that the new block should go
at the beginning of the list of blocks at this binding level,
rather than the end. This hack is no longer used. */
- my_friendly_assert (keep == 0 || keep == 1, 0);
+ gcc_assert (keep == 0 || keep == 1);
if (current_binding_level->keep)
keep = 1;
/* Any uses of undefined labels, and any defined labels, now operate
under constraints of next binding contour. */
- if (cfun && !functionbody)
- {
- struct cp_binding_level *level_chain;
- level_chain = current_binding_level->level_chain;
- if (level_chain)
- {
- struct named_label_use_list *uses;
- struct named_label_list *labels;
- for (labels = named_labels; labels; labels = labels->next)
- if (labels->binding_level == current_binding_level)
- {
- tree decl;
- if (current_binding_level->kind == sk_try)
- labels->in_try_scope = 1;
- if (current_binding_level->kind == sk_catch)
- labels->in_catch_scope = 1;
- for (decl = labels->names_in_scope; decl;
- decl = TREE_CHAIN (decl))
- if (decl_jump_unsafe (decl))
- labels->bad_decls = tree_cons (NULL_TREE, decl,
- labels->bad_decls);
- labels->binding_level = level_chain;
- labels->names_in_scope = level_chain->names;
- }
-
- for (uses = named_label_uses; uses; uses = uses->next)
- if (uses->binding_level == current_binding_level)
- {
- uses->binding_level = level_chain;
- uses->names_in_scope = level_chain->names;
- }
- }
- }
+ if (cfun && !functionbody && named_labels)
+ htab_traverse (named_labels, poplevel_named_label_1,
+ current_binding_level);
/* Get the decls in the order they were written.
Usually current_binding_level->names is in reverse order.
@@ -500,36 +575,6 @@ poplevel (int keep, int reverse, int functionbody)
else
decls = current_binding_level->names;
- /* Output any nested inline functions within this block
- if they weren't already output. */
- for (decl = decls; decl; decl = TREE_CHAIN (decl))
- if (TREE_CODE (decl) == FUNCTION_DECL
- && ! TREE_ASM_WRITTEN (decl)
- && DECL_INITIAL (decl) != NULL_TREE
- && TREE_ADDRESSABLE (decl)
- && decl_function_context (decl) == current_function_decl)
- {
- /* If this decl was copied from a file-scope decl
- on account of a block-scope extern decl,
- propagate TREE_ADDRESSABLE to the file-scope decl. */
- if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE)
- TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
- else
- {
- push_function_context ();
- output_inline_function (decl);
- pop_function_context ();
- }
- }
-
- /* When not in function-at-a-time mode, expand_end_bindings will
- warn about unused variables. But, in function-at-a-time mode
- expand_end_bindings is not passed the list of variables in the
- current scope, and therefore no warning is emitted. So, we
- explicitly warn here. */
- if (!processing_template_decl)
- warn_about_unused_variables (getdecls ());
-
/* If there were any declarations or structure tags in that level,
or if this level is a function body,
create a BLOCK to record them for the life of this function. */
@@ -554,33 +599,44 @@ poplevel (int keep, int reverse, int functionbody)
leaving_for_scope
= current_binding_level->kind == sk_for && flag_new_for_scope == 1;
+ /* Before we remove the declarations first check for unused variables. */
+ if (warn_unused_variable
+ && !processing_template_decl)
+ for (decl = getdecls (); decl; decl = TREE_CHAIN (decl))
+ if (TREE_CODE (decl) == VAR_DECL
+ && ! TREE_USED (decl)
+ && ! DECL_IN_SYSTEM_HEADER (decl)
+ && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
+ warning (OPT_Wunused_variable, "unused variable %q+D", decl);
+
/* Remove declarations for all the DECLs in this level. */
for (link = decls; link; link = TREE_CHAIN (link))
{
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
- && DECL_NAME (link))
+ && DECL_NAME (link))
{
- cxx_binding *outer_binding
- = IDENTIFIER_BINDING (DECL_NAME (link))->previous;
+ tree name = DECL_NAME (link);
+ cxx_binding *ob;
tree ns_binding;
- if (!outer_binding)
- ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
+ ob = outer_binding (name,
+ IDENTIFIER_BINDING (name),
+ /*class_p=*/true);
+ if (!ob)
+ ns_binding = IDENTIFIER_NAMESPACE_VALUE (name);
else
ns_binding = NULL_TREE;
- if (outer_binding
- && outer_binding->scope == current_binding_level->level_chain)
+ if (ob && ob->scope == current_binding_level->level_chain)
/* We have something like:
- int i;
- for (int i; ;);
+ int i;
+ for (int i; ;);
and we are leaving the `for' scope. There's no reason to
keep the binding of the inner `i' in this case. */
- pop_binding (DECL_NAME (link), link);
- else if ((outer_binding
- && (TREE_CODE (outer_binding->value) == TYPE_DECL))
+ pop_binding (name, link);
+ else if ((ob && (TREE_CODE (ob->value) == TYPE_DECL))
|| (ns_binding && TREE_CODE (ns_binding) == TYPE_DECL))
/* Here, we have something like:
@@ -592,7 +648,7 @@ poplevel (int keep, int reverse, int functionbody)
We must pop the for-scope binding so we know what's a
type and what isn't. */
- pop_binding (DECL_NAME (link), link);
+ pop_binding (name, link);
else
{
/* Mark this VAR_DECL as dead so that we can tell we left it
@@ -601,8 +657,11 @@ poplevel (int keep, int reverse, int functionbody)
/* Keep track of what should have happened when we
popped the binding. */
- if (outer_binding && outer_binding->value)
- DECL_SHADOWED_FOR_VAR (link) = outer_binding->value;
+ if (ob && ob->value)
+ {
+ SET_DECL_SHADOWED_FOR_VAR (link, ob->value);
+ DECL_HAS_SHADOWED_FOR_VAR_P (link) = 1;
+ }
/* Add it to the list of dead variables in the next
outermost binding to that we can remove these when we
@@ -614,21 +673,26 @@ poplevel (int keep, int reverse, int functionbody)
/* Although we don't pop the cxx_binding, we do clear
its SCOPE since the scope is going away now. */
- IDENTIFIER_BINDING (DECL_NAME (link))->scope = NULL;
+ IDENTIFIER_BINDING (name)->scope
+ = current_binding_level->level_chain;
}
}
else
{
+ tree name;
+
/* Remove the binding. */
decl = link;
+
if (TREE_CODE (decl) == TREE_LIST)
decl = TREE_VALUE (decl);
- if (DECL_P (decl))
- pop_binding (DECL_NAME (decl), decl);
- else if (TREE_CODE (decl) == OVERLOAD)
- pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
- else
- abort ();
+ name = decl;
+
+ if (TREE_CODE (name) == OVERLOAD)
+ name = OVL_FUNCTION (name);
+
+ gcc_assert (DECL_P (name));
+ pop_binding (DECL_NAME (name), decl);
}
}
@@ -647,7 +711,7 @@ poplevel (int keep, int reverse, int functionbody)
for (link = current_binding_level->shadowed_labels;
link;
link = TREE_CHAIN (link))
- pop_label (TREE_VALUE (link), TREE_PURPOSE (link));
+ pop_local_label (TREE_VALUE (link), TREE_PURPOSE (link));
/* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
list if a `using' declaration put them there. The debugging
@@ -680,6 +744,17 @@ poplevel (int keep, int reverse, int functionbody)
}
kind = current_binding_level->kind;
+ if (kind == sk_cleanup)
+ {
+ tree stmt;
+
+ /* If this is a temporary binding created for a cleanup, then we'll
+ have pushed a statement list level. Pop that, create a new
+ BIND_EXPR for the block, and insert it into the stream. */
+ stmt = pop_stmt_list (current_binding_level->statement_list);
+ stmt = c_build_bind_expr (block, stmt);
+ add_stmt (stmt);
+ }
leave_scope ();
if (functionbody)
@@ -703,48 +778,13 @@ poplevel (int keep, int reverse, int functionbody)
if (block)
TREE_USED (block) = 1;
- /* Take care of compiler's internal binding structures. */
+ /* All temporary bindings created for cleanups are popped silently. */
if (kind == sk_cleanup)
- {
- tree scope_stmts;
-
- scope_stmts
- = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1);
- if (block)
- {
- SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
- SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
- }
-
- block = poplevel (keep, reverse, functionbody);
- }
+ goto restart;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
-/* Delete the node BLOCK from the current binding level.
- This is used for the block inside a stmt expr ({...})
- so that the block can be reinserted where appropriate. */
-
-void
-delete_block (tree block)
-{
- tree t;
- if (current_binding_level->blocks == block)
- current_binding_level->blocks = TREE_CHAIN (block);
- for (t = current_binding_level->blocks; t;)
- {
- if (TREE_CHAIN (t) == block)
- TREE_CHAIN (t) = TREE_CHAIN (block);
- else
- t = TREE_CHAIN (t);
- }
- TREE_CHAIN (block) = NULL_TREE;
- /* Clear TREE_USED which is always set by poplevel.
- The flag is set again if insert_block is called. */
- TREE_USED (block) = 0;
-}
-
/* Insert BLOCK at the end of the list of subblocks of the
current binding level. This is used when a BIND_EXPR is expanded,
to handle the BLOCK node inside the BIND_EXPR. */
@@ -757,74 +797,6 @@ insert_block (tree block)
= chainon (current_binding_level->blocks, block);
}
-/* Set the BLOCK node for the innermost scope
- (the one we are currently in). */
-
-void
-set_block (tree block ATTRIBUTE_UNUSED )
-{
- /* The RTL expansion machinery requires us to provide this callback,
- but it is not applicable in function-at-a-time mode. */
-}
-
-/* Returns nonzero if T is a virtual function table. */
-
-int
-vtable_decl_p (tree t, void* data ATTRIBUTE_UNUSED )
-{
- return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
-}
-
-/* Returns nonzero if T is a TYPE_DECL for a type with virtual
- functions. */
-
-int
-vtype_decl_p (tree t, void *data ATTRIBUTE_UNUSED )
-{
- return (TREE_CODE (t) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
- && TYPE_POLYMORPHIC_P (TREE_TYPE (t)));
-}
-
-struct walk_globals_data {
- walk_globals_pred p;
- walk_globals_fn f;
- void *data;
-};
-
-/* Walk the vtable declarations in NAMESPACE. Whenever one is found
- for which P returns nonzero, call F with its address. If any call
- to F returns a nonzero value, return a nonzero value. */
-
-static int
-walk_vtables_r (tree namespace, void* data)
-{
- struct walk_globals_data* wgd = (struct walk_globals_data *) data;
- walk_globals_fn f = wgd->f;
- void *d = wgd->data;
- tree decl = NAMESPACE_LEVEL (namespace)->vtables;
- int result = 0;
-
- for (; decl ; decl = TREE_CHAIN (decl))
- result |= (*f) (&decl, d);
-
- return result;
-}
-
-/* Walk the vtable declarations. Whenever one is found for which P
- returns nonzero, call F with its address. If any call to F
- returns a nonzero value, return a nonzero value. */
-bool
-walk_vtables (walk_globals_pred p, walk_globals_fn f, void *data)
-{
- struct walk_globals_data wgd;
- wgd.p = p;
- wgd.f = f;
- wgd.data = data;
-
- return walk_namespaces (walk_vtables_r, &wgd);
-}
-
/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
itself, calling F for each. The DATA is passed to F as well. */
@@ -832,7 +804,7 @@ static int
walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data)
{
int result = 0;
- tree current = NAMESPACE_LEVEL (namespace)->namespaces;
+ tree current = NAMESPACE_LEVEL (namespace)->namespaces;
result |= (*f) (namespace, data);
@@ -851,53 +823,6 @@ walk_namespaces (walk_namespaces_fn f, void* data)
return walk_namespaces_r (global_namespace, f, data);
}
-/* Walk the global declarations in NAMESPACE. Whenever one is found
- for which P returns nonzero, call F with its address. If any call
- to F returns a nonzero value, return a nonzero value. */
-
-static int
-walk_globals_r (tree namespace, void* data)
-{
- struct walk_globals_data* wgd = (struct walk_globals_data *) data;
- walk_globals_pred p = wgd->p;
- walk_globals_fn f = wgd->f;
- void *d = wgd->data;
- tree *t;
- int result = 0;
-
- t = &NAMESPACE_LEVEL (namespace)->names;
-
- while (*t)
- {
- tree glbl = *t;
-
- if ((*p) (glbl, d))
- result |= (*f) (t, d);
-
- /* If F changed *T, then *T still points at the next item to
- examine. */
- if (*t == glbl)
- t = &TREE_CHAIN (*t);
- }
-
- return result;
-}
-
-/* Walk the global declarations. Whenever one is found for which P
- returns true, call F with its address. If any call to F
- returns true, return true. */
-
-bool
-walk_globals (walk_globals_pred p, walk_globals_fn f, void *data)
-{
- struct walk_globals_data wgd;
- wgd.p = p;
- wgd.f = f;
- wgd.data = data;
-
- return walk_namespaces (walk_globals_r, &wgd);
-}
-
/* Call wrapup_globals_declarations for the globals in NAMESPACE. If
DATA is non-NULL, this is the last time we will call
wrapup_global_declarations for this NAMESPACE. */
@@ -906,14 +831,15 @@ int
wrapup_globals_for_namespace (tree namespace, void* data)
{
struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
- varray_type statics = level->static_decls;
- tree *vec = &VARRAY_TREE (statics, 0);
- int len = VARRAY_ACTIVE_SIZE (statics);
+ VEC(tree,gc) *statics = level->static_decls;
+ tree *vec = VEC_address (tree, statics);
+ int len = VEC_length (tree, statics);
int last_time = (data != 0);
if (last_time)
{
check_global_declarations (vec, len);
+ emit_debug_global_declarations (vec, len);
return 0;
}
@@ -952,15 +878,13 @@ push_local_name (tree decl)
tree t, name;
timevar_push (TV_NAME_LOOKUP);
- if (!local_names)
- VARRAY_TREE_INIT (local_names, 8, "local_names");
name = DECL_NAME (decl);
- nelts = VARRAY_ACTIVE_SIZE (local_names);
+ nelts = VEC_length (tree, local_names);
for (i = 0; i < nelts; i++)
{
- t = VARRAY_TREE (local_names, i);
+ t = VEC_index (tree, local_names, i);
if (DECL_NAME (t) == name)
{
if (!DECL_LANG_SPECIFIC (decl))
@@ -971,13 +895,13 @@ push_local_name (tree decl)
else
DECL_DISCRIMINATOR (decl) = 1;
- VARRAY_TREE (local_names, i) = decl;
+ VEC_replace (tree, local_names, i, decl);
timevar_pop (TV_NAME_LOOKUP);
return;
}
}
- VARRAY_PUSH_TREE (local_names, decl);
+ VEC_safe_push (tree, gc, local_names, decl);
timevar_pop (TV_NAME_LOOKUP);
}
@@ -1014,15 +938,15 @@ decls_match (tree newdecl, tree olddecl)
return 0;
if (TREE_CODE (f1) != TREE_CODE (f2))
- return 0;
+ return 0;
if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
if (p2 == NULL_TREE && DECL_EXTERN_C_P (olddecl)
&& (DECL_BUILT_IN (olddecl)
#ifndef NO_IMPLICIT_EXTERN_C
- || (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
- || (DECL_IN_SYSTEM_HEADER (olddecl) && !DECL_CLASS_SCOPE_P (olddecl))
+ || (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
+ || (DECL_IN_SYSTEM_HEADER (olddecl) && !DECL_CLASS_SCOPE_P (olddecl))
#endif
))
{
@@ -1033,11 +957,11 @@ decls_match (tree newdecl, tree olddecl)
#ifndef NO_IMPLICIT_EXTERN_C
else if (p1 == NULL_TREE
&& (DECL_EXTERN_C_P (olddecl)
- && DECL_IN_SYSTEM_HEADER (olddecl)
- && !DECL_CLASS_SCOPE_P (olddecl))
+ && DECL_IN_SYSTEM_HEADER (olddecl)
+ && !DECL_CLASS_SCOPE_P (olddecl))
&& (DECL_EXTERN_C_P (newdecl)
- && DECL_IN_SYSTEM_HEADER (newdecl)
- && !DECL_CLASS_SCOPE_P (newdecl)))
+ && DECL_IN_SYSTEM_HEADER (newdecl)
+ && !DECL_CLASS_SCOPE_P (newdecl)))
{
types_match = self_promoting_args_p (p2);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
@@ -1071,7 +995,13 @@ decls_match (tree newdecl, tree olddecl)
/* Need to check scope for variable declaration (VAR_DECL).
For typedef (TYPE_DECL), scope is ignored. */
if (TREE_CODE (newdecl) == VAR_DECL
- && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
+ && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
+ /* [dcl.link]
+ Two declarations for an object with C language linkage
+ with the same name (ignoring the namespace that qualify
+ it) that appear in different namespace scopes refer to
+ the same object. */
+ && !(DECL_EXTERN_C_P (olddecl) && DECL_EXTERN_C_P (newdecl)))
return 0;
if (TREE_TYPE (newdecl) == error_mark_node)
@@ -1101,11 +1031,6 @@ decls_match (tree newdecl, tree olddecl)
void
warn_extern_redeclared_static (tree newdecl, tree olddecl)
{
- static const char *const explicit_extern_static_warning
- = "`%D' was declared `extern' and later `static'";
- static const char *const implicit_extern_static_warning
- = "`%D' was declared implicitly `extern' and later `static'";
-
tree name;
if (TREE_CODE (newdecl) == TYPE_DECL
@@ -1131,10 +1056,43 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
return;
name = DECL_ASSEMBLER_NAME (newdecl);
- pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
- ? implicit_extern_static_warning
- : explicit_extern_static_warning, newdecl);
- cp_pedwarn_at ("previous declaration of `%D'", olddecl);
+ pedwarn ("%qD was declared %<extern%> and later %<static%>", newdecl);
+ pedwarn ("previous declaration of %q+D", olddecl);
+}
+
+/* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
+ function templates. If their exception specifications do not
+ match, issue an a diagnostic. */
+
+static void
+check_redeclaration_exception_specification (tree new_decl,
+ tree old_decl)
+{
+ tree new_type;
+ tree old_type;
+ tree new_exceptions;
+ tree old_exceptions;
+
+ new_type = TREE_TYPE (new_decl);
+ new_exceptions = TYPE_RAISES_EXCEPTIONS (new_type);
+ old_type = TREE_TYPE (old_decl);
+ old_exceptions = TYPE_RAISES_EXCEPTIONS (old_type);
+
+ /* [except.spec]
+
+ If any declaration of a function has an exception-specification,
+ all declarations, including the definition and an explicit
+ specialization, of that function shall have an
+ exception-specification with the same set of type-ids. */
+ if ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
+ && ! DECL_IS_BUILTIN (old_decl)
+ && flag_exceptions
+ && !comp_except_specs (new_exceptions, old_exceptions,
+ /*exact=*/true))
+ {
+ error ("declaration of %qF throws different exceptions", new_decl);
+ error ("from previous declaration %q+F", old_decl);
+ }
}
/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
@@ -1142,14 +1100,17 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
error_mark_node is returned. Otherwise, OLDDECL is returned.
If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
- returned. */
+ returned.
+
+ NEWDECL_IS_FRIEND is true if NEWDECL was declared as a friend. */
tree
-duplicate_decls (tree newdecl, tree olddecl)
+duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
{
unsigned olddecl_uid = DECL_UID (olddecl);
- int olddecl_friend = 0, types_match = 0;
+ int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
int new_defines_function = 0;
+ tree new_template;
if (newdecl == olddecl)
return olddecl;
@@ -1163,7 +1124,7 @@ duplicate_decls (tree newdecl, tree olddecl)
about the same declaration, so just pretend the types match here. */
if (TREE_TYPE (newdecl) == error_mark_node
|| TREE_TYPE (olddecl) == error_mark_node)
- types_match = 1;
+ return error_mark_node;
if (DECL_P (olddecl)
&& TREE_CODE (newdecl) == FUNCTION_DECL
@@ -1182,18 +1143,19 @@ duplicate_decls (tree newdecl, tree olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl);
- warning ("%Jprevious declaration of '%D' with attribute noinline",
- olddecl, olddecl);
+ warning (OPT_Wattributes, "function %q+D redeclared as inline",
+ newdecl);
+ warning (OPT_Wattributes, "previous declaration of %q+D "
+ "with attribute noinline", olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warning ("%Jfunction '%D' redeclared with attribute noinline",
- newdecl, newdecl);
- warning ("%Jprevious declaration of '%D' was inline",
- olddecl, olddecl);
+ warning (OPT_Wattributes, "function %q+D redeclared with "
+ "attribute noinline", newdecl);
+ warning (OPT_Wattributes, "previous declaration of %q+D was inline",
+ olddecl);
}
}
@@ -1201,42 +1163,78 @@ duplicate_decls (tree newdecl, tree olddecl)
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
{
+ gcc_assert (!DECL_HIDDEN_FRIEND_P (olddecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
- /* Avoid warnings redeclaring anticipated built-ins. */
- if (DECL_ANTICIPATED (olddecl))
- return NULL_TREE;
+ /* Avoid warnings redeclaring built-ins which have not been
+ explicitly declared. */
+ if (DECL_ANTICIPATED (olddecl))
+ return NULL_TREE;
/* If you declare a built-in or predefined function name as static,
the old definition is overridden, but optionally warn this was a
bad choice of name. */
if (! TREE_PUBLIC (newdecl))
{
- if (warn_shadow)
- warning ("shadowing %s function `%#D'",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- olddecl);
+ warning (OPT_Wshadow, "shadowing %s function %q#D",
+ DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+ olddecl);
/* Discard the old built-in function. */
return NULL_TREE;
}
/* If the built-in is not ansi, then programs can override
it even globally without an error. */
else if (! DECL_BUILT_IN (olddecl))
- warning ("library function `%#D' redeclared as non-function `%#D'",
- olddecl, newdecl);
+ warning (0, "library function %q#D redeclared as non-function %q#D",
+ olddecl, newdecl);
else
{
- error ("declaration of `%#D'", newdecl);
- error ("conflicts with built-in declaration `%#D'",
- olddecl);
+ error ("declaration of %q#D", newdecl);
+ error ("conflicts with built-in declaration %q#D",
+ olddecl);
}
return NULL_TREE;
}
else if (!types_match)
{
- /* Avoid warnings redeclaring anticipated built-ins. */
- if (DECL_ANTICIPATED (olddecl))
- ; /* Do nothing yet. */
+ /* Avoid warnings redeclaring built-ins which have not been
+ explicitly declared. */
+ if (DECL_ANTICIPATED (olddecl))
+ {
+ /* Deal with fileptr_type_node. FILE type is not known
+ at the time we create the builtins. */
+ tree t1, t2;
+
+ for (t1 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
+ t2 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
+ t1 || t2;
+ t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
+ if (!t1 || !t2)
+ break;
+ else if (TREE_VALUE (t2) == fileptr_type_node)
+ {
+ tree t = TREE_VALUE (t1);
+
+ if (TREE_CODE (t) == POINTER_TYPE
+ && TYPE_NAME (TREE_TYPE (t))
+ && DECL_NAME (TYPE_NAME (TREE_TYPE (t)))
+ == get_identifier ("FILE")
+ && compparms (TREE_CHAIN (t1), TREE_CHAIN (t2)))
+ {
+ tree oldargs = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
+
+ TYPE_ARG_TYPES (TREE_TYPE (olddecl))
+ = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
+ types_match = decls_match (newdecl, olddecl);
+ if (types_match)
+ return duplicate_decls (newdecl, olddecl,
+ newdecl_is_friend);
+ TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs;
+ }
+ }
+ else if (! same_type_p (TREE_VALUE (t1), TREE_VALUE (t2)))
+ break;
+ }
else if ((DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl))
|| compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
@@ -1246,24 +1244,25 @@ duplicate_decls (tree newdecl, tree olddecl)
if (TREE_PUBLIC (newdecl))
{
- warning ("new declaration `%#D'", newdecl);
- warning ("ambiguates built-in declaration `%#D'",
- olddecl);
+ warning (0, "new declaration %q#D", newdecl);
+ warning (0, "ambiguates built-in declaration %q#D",
+ olddecl);
}
- else if (warn_shadow)
- warning ("shadowing %s function `%#D'",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- olddecl);
+ else
+ warning (OPT_Wshadow, "shadowing %s function %q#D",
+ DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+ olddecl);
}
else
/* Discard the old built-in function. */
return NULL_TREE;
/* Replace the old RTL to avoid problems with inlining. */
- SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
+ COPY_DECL_RTL (newdecl, olddecl);
}
- /* Even if the types match, prefer the new declarations type
- for anticipated built-ins, for exception lists, etc... */
+ /* Even if the types match, prefer the new declarations type for
+ built-ins which have not been explicitly declared, for
+ exception lists, etc... */
else if (DECL_ANTICIPATED (olddecl))
{
tree type = TREE_TYPE (newdecl);
@@ -1289,7 +1288,7 @@ duplicate_decls (tree newdecl, tree olddecl)
that all remnants of the builtin-ness of this function
will be banished. */
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
- SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
+ COPY_DECL_RTL (newdecl, olddecl);
}
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
@@ -1318,15 +1317,12 @@ duplicate_decls (tree newdecl, tree olddecl)
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
return NULL_TREE;
- error ("`%#D' redeclared as different kind of symbol", newdecl);
+ error ("%q#D redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
- cp_error_at ("previous declaration of `%#D'", olddecl);
-
- /* New decl is completely inconsistent with the old one =>
- tell caller to replace the old one. */
+ error ("previous declaration of %q+#D", olddecl);
- return NULL_TREE;
+ return error_mark_node;
}
else if (!types_match)
{
@@ -1343,9 +1339,8 @@ duplicate_decls (tree newdecl, tree olddecl)
if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
|| TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
- error ("declaration of template `%#D'", newdecl);
- cp_error_at ("conflicts with previous declaration `%#D'",
- olddecl);
+ error ("declaration of template %q#D", newdecl);
+ error ("conflicts with previous declaration %q+#D", olddecl);
}
else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
@@ -1358,8 +1353,8 @@ duplicate_decls (tree newdecl, tree olddecl)
&& same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
TREE_TYPE (TREE_TYPE (olddecl))))
{
- error ("new declaration `%#D'", newdecl);
- cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ error ("new declaration %q#D", newdecl);
+ error ("ambiguates old declaration %q+#D", olddecl);
}
return NULL_TREE;
}
@@ -1367,25 +1362,25 @@ duplicate_decls (tree newdecl, tree olddecl)
{
if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
{
- error ("declaration of C function `%#D' conflicts with",
- newdecl);
- cp_error_at ("previous declaration `%#D' here", olddecl);
+ error ("declaration of C function %q#D conflicts with",
+ newdecl);
+ error ("previous declaration %q+#D here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
- error ("new declaration `%#D'", newdecl);
- cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ error ("new declaration %q#D", newdecl);
+ error ("ambiguates old declaration %q+#D", olddecl);
+ return error_mark_node;
}
else
return NULL_TREE;
}
else
{
- error ("conflicting declaration '%#D'", newdecl);
- cp_error_at ("'%D' has a previous declaration as `%#D'",
- olddecl, olddecl);
- return NULL_TREE;
+ error ("conflicting declaration %q#D", newdecl);
+ error ("%q+D has a previous declaration as %q#D", olddecl, olddecl);
+ return error_mark_node;
}
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -1417,27 +1412,27 @@ duplicate_decls (tree newdecl, tree olddecl)
else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
{
/* In [namespace.alias] we have:
-
- In a declarative region, a namespace-alias-definition can be
+
+ In a declarative region, a namespace-alias-definition can be
used to redefine a namespace-alias declared in that declarative
region to refer only to the namespace to which it already
refers.
-
+
Therefore, if we encounter a second alias directive for the same
alias, we can just ignore the second directive. */
if (DECL_NAMESPACE_ALIAS (newdecl)
- && (DECL_NAMESPACE_ALIAS (newdecl)
+ && (DECL_NAMESPACE_ALIAS (newdecl)
== DECL_NAMESPACE_ALIAS (olddecl)))
return olddecl;
/* [namespace.alias]
- A namespace-name or namespace-alias shall not be declared as
+ A namespace-name or namespace-alias shall not be declared as
the name of any other entity in the same declarative region.
A namespace-name defined at global scope shall not be
- declared as the name of any other entity in any glogal scope
+ declared as the name of any other entity in any global scope
of the program. */
- error ("declaration of `namespace %D' conflicts with", newdecl);
- cp_error_at ("previous declaration of `namespace %D' here", olddecl);
+ error ("declaration of namespace %qD conflicts with", newdecl);
+ error ("previous declaration of namespace %q+D here", olddecl);
return error_mark_node;
}
else
@@ -1447,10 +1442,9 @@ duplicate_decls (tree newdecl, tree olddecl)
{
error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
- cp_error_at ((DECL_INITIAL (olddecl)
- && namespace_bindings_p ())
- ? "`%#D' previously defined here"
- : "`%#D' previously declared here", olddecl);
+ error ((DECL_INITIAL (olddecl) && namespace_bindings_p ())
+ ? "%q+#D previously defined here"
+ : "%q+#D previously declared here", olddecl);
return error_mark_node;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1459,23 +1453,51 @@ duplicate_decls (tree newdecl, tree olddecl)
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
{
/* Prototype decl follows defn w/o prototype. */
- cp_warning_at ("prototype for `%#D'", newdecl);
- warning ("%Jfollows non-prototype definition here", olddecl);
+ warning (0, "prototype for %q+#D", newdecl);
+ warning (0, "%Jfollows non-prototype definition here", olddecl);
}
- else if (TREE_CODE (olddecl) == FUNCTION_DECL
+ else if ((TREE_CODE (olddecl) == FUNCTION_DECL
+ || TREE_CODE (olddecl) == VAR_DECL)
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
{
- /* extern "C" int foo ();
- int foo () { bar (); }
- is OK. */
+ /* [dcl.link]
+ If two declarations of the same function or object
+ specify different linkage-specifications ..., the program
+ is ill-formed.... Except for functions with C++ linkage,
+ a function declaration without a linkage specification
+ shall not precede the first linkage specification for
+ that function. A function can be declared without a
+ linkage specification after an explicit linkage
+ specification has been seen; the linkage explicitly
+ specified in the earlier declaration is not affected by
+ such a function declaration.
+
+ DR 563 raises the question why the restrictions on
+ functions should not also apply to objects. Older
+ versions of G++ silently ignore the linkage-specification
+ for this example:
+
+ namespace N {
+ extern int i;
+ extern "C" int i;
+ }
+
+ which is clearly wrong. Therefore, we now treat objects
+ like functions. */
if (current_lang_depth () == 0)
- SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+ {
+ /* There is no explicit linkage-specification, so we use
+ the linkage from the previous declaration. */
+ if (!DECL_LANG_SPECIFIC (newdecl))
+ retrofit_lang_decl (newdecl);
+ SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+ }
else
{
- cp_error_at ("previous declaration of `%#D' with %L linkage",
- olddecl, DECL_LANGUAGE (olddecl));
- error ("conflicts with new declaration with %L linkage",
- DECL_LANGUAGE (newdecl));
+ error ("previous declaration of %q+#D with %qL linkage",
+ olddecl, DECL_LANGUAGE (olddecl));
+ error ("conflicts with new declaration with %qL linkage",
+ DECL_LANGUAGE (newdecl));
}
}
@@ -1497,26 +1519,25 @@ duplicate_decls (tree newdecl, tree olddecl)
if (1 == simple_cst_equal (TREE_PURPOSE (t1),
TREE_PURPOSE (t2)))
{
- pedwarn ("default argument given for parameter %d of `%#D'",
+ pedwarn ("default argument given for parameter %d of %q#D",
i, newdecl);
- cp_pedwarn_at ("after previous specification in `%#D'",
- olddecl);
+ pedwarn ("after previous specification in %q+#D", olddecl);
}
else
{
- error ("default argument given for parameter %d of `%#D'",
- i, newdecl);
- cp_error_at ("after previous specification in `%#D'",
+ error ("default argument given for parameter %d of %q#D",
+ i, newdecl);
+ error ("after previous specification in %q+#D",
olddecl);
}
}
- if (DECL_DECLARED_INLINE_P (newdecl)
+ if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
- warning ("`%#D' was used before it was declared inline", newdecl);
- warning ("%Jprevious non-inline declaration here", olddecl);
+ warning (0, "%q#D was used before it was declared inline", newdecl);
+ warning (0, "%Jprevious non-inline declaration here", olddecl);
}
}
}
@@ -1552,7 +1573,6 @@ duplicate_decls (tree newdecl, tree olddecl)
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
- DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
SET_OVERLOADED_OPERATOR_CODE
@@ -1560,17 +1580,17 @@ duplicate_decls (tree newdecl, tree olddecl)
new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
/* Optionally warn about more than one declaration for the same
- name, but don't warn about a function declaration followed by a
- definition. */
+ name, but don't warn about a function declaration followed by a
+ definition. */
if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
/* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
/* Don't warn about friends, let add_friend take care of it. */
- && ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
+ && ! (newdecl_is_friend || DECL_FRIEND_P (olddecl)))
{
- warning ("redundant redeclaration of `%D' in same scope", newdecl);
- cp_warning_at ("previous declaration of `%D'", olddecl);
+ warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
+ warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl);
}
}
@@ -1595,30 +1615,35 @@ duplicate_decls (tree newdecl, tree olddecl)
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
- TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
+ tree old_result;
+ tree new_result;
+ old_result = DECL_TEMPLATE_RESULT (olddecl);
+ new_result = DECL_TEMPLATE_RESULT (newdecl);
+ TREE_TYPE (olddecl) = TREE_TYPE (old_result);
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
+ if (DECL_FUNCTION_TEMPLATE_P (newdecl))
+ {
+ DECL_INLINE (old_result)
+ |= DECL_INLINE (new_result);
+ DECL_DECLARED_INLINE_P (old_result)
+ |= DECL_DECLARED_INLINE_P (new_result);
+ check_redeclaration_exception_specification (newdecl, olddecl);
+ }
+
/* If the new declaration is a definition, update the file and
line information on the declaration. */
- if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
- && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
+ if (DECL_INITIAL (old_result) == NULL_TREE
+ && DECL_INITIAL (new_result) != NULL_TREE)
{
- DECL_SOURCE_LOCATION (olddecl)
- = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
+ DECL_SOURCE_LOCATION (olddecl)
+ = DECL_SOURCE_LOCATION (old_result)
= DECL_SOURCE_LOCATION (newdecl);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
- DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
- = DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
- }
-
- if (DECL_FUNCTION_TEMPLATE_P (newdecl))
- {
- DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl))
- |= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl));
- DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl))
- |= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl));
+ DECL_ARGUMENTS (old_result)
+ = DECL_ARGUMENTS (new_result);
}
return olddecl;
@@ -1642,34 +1667,33 @@ duplicate_decls (tree newdecl, tree olddecl)
{
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
+ DECL_NONTRIVIALLY_INITIALIZED_P (newdecl)
+ |= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
- }
- /* Do this after calling `merge_types' so that default
- parameters don't confuse us. */
- else if (TREE_CODE (newdecl) == FUNCTION_DECL
- && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
- != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
- {
- TREE_TYPE (newdecl) = build_exception_variant (newtype,
- TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
- TREE_TYPE (olddecl) = build_exception_variant (newtype,
- TYPE_RAISES_EXCEPTIONS (oldtype));
-
- if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
- && DECL_SOURCE_LINE (olddecl) != 0
- && flag_exceptions
- && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
- TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
+ /* Merge the threadprivate attribute from OLDDECL into NEWDECL. */
+ if (DECL_LANG_SPECIFIC (olddecl)
+ && CP_DECL_THREADPRIVATE_P (olddecl))
{
- error ("declaration of `%F' throws different exceptions",
- newdecl);
- cp_error_at ("than previous declaration `%F'", olddecl);
+ /* Allocate a LANG_SPECIFIC structure for NEWDECL, if needed. */
+ if (!DECL_LANG_SPECIFIC (newdecl))
+ retrofit_lang_decl (newdecl);
+
+ DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
+ CP_DECL_THREADPRIVATE_P (newdecl) = 1;
}
}
+
+ /* Do this after calling `merge_types' so that default
+ parameters don't confuse us. */
+ else if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ check_redeclaration_exception_specification (newdecl, olddecl);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ check_default_args (newdecl);
+
/* Lay the type out, unless already done. */
if (! same_type_p (newtype, oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
@@ -1689,6 +1713,12 @@ duplicate_decls (tree newdecl, tree olddecl)
TREE_READONLY (olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (olddecl) = 1;
+ if (TREE_NOTHROW (newdecl))
+ TREE_NOTHROW (olddecl) = 1;
+
+ /* Merge deprecatedness. */
+ if (TREE_DEPRECATED (newdecl))
+ TREE_DEPRECATED (olddecl) = 1;
/* Merge the initialization information. */
if (DECL_INITIAL (newdecl) == NULL_TREE
@@ -1701,12 +1731,12 @@ duplicate_decls (tree newdecl, tree olddecl)
&& DECL_LANG_SPECIFIC (olddecl))
{
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
- DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
+ DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
}
}
/* Merge the section attribute.
- We want to issue an error if the sections conflict but that must be
+ We want to issue an error if the sections conflict but that must be
done later in decl_attributes since we are called before attributes
are assigned. */
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
@@ -1725,7 +1755,7 @@ duplicate_decls (tree newdecl, tree olddecl)
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}
- else if (TREE_CODE (newdecl) == VAR_DECL
+ else if (TREE_CODE (newdecl) == VAR_DECL
&& (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
{
/* Keep the old RTL. We cannot keep the old RTL if the old
@@ -1760,6 +1790,7 @@ duplicate_decls (tree newdecl, tree olddecl)
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
+ new_template = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
@@ -1767,16 +1798,30 @@ duplicate_decls (tree newdecl, tree olddecl)
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
+
+ /* If the OLDDECL is an instantiation and/or specialization,
+ then the NEWDECL must be too. But, it may not yet be marked
+ as such if the caller has created NEWDECL, but has not yet
+ figured out that it is a redeclaration. */
+ if (!DECL_USE_TEMPLATE (newdecl))
+ DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
+ DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+ DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
+ if (DECL_TEMPLATE_INFO (newdecl))
+ new_template = DECL_TI_TEMPLATE (newdecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
- |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
+ |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
+ hidden_friend = (DECL_ANTICIPATED (olddecl)
+ && DECL_HIDDEN_FRIEND_P (olddecl)
+ && newdecl_is_friend);
/* Only functions have DECL_BEFRIENDING_CLASSES. */
if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -1800,8 +1845,7 @@ duplicate_decls (tree newdecl, tree olddecl)
/* If newdecl is not a specialization, then it is not a
template-related function at all. And that means that we
should have exited above, returning 0. */
- my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
- 0);
+ gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl));
if (TREE_USED (olddecl))
/* From [temp.expl.spec]:
@@ -1812,11 +1856,16 @@ duplicate_decls (tree newdecl, tree olddecl)
that specialization that would cause an implicit
instantiation to take place, in every translation unit in
which such a use occurs. */
- error ("explicit specialization of %D after first use",
+ error ("explicit specialization of %qD after first use",
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
+ /* Don't propagate visibility from the template to the
+ specialization here. We'll do that in determine_visibility if
+ appropriate. */
+ DECL_VISIBILITY_SPECIFIED (olddecl) = 0;
+
/* [temp.expl.spec/14] We don't inline explicit specialization
just because the primary template says so. */
}
@@ -1827,7 +1876,7 @@ duplicate_decls (tree newdecl, tree olddecl)
DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
- /* If either decl says `inline', this fn is inline, unless
+ /* If either decl says `inline', this fn is inline, unless
its definition was passed already. */
if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1;
@@ -1844,7 +1893,7 @@ duplicate_decls (tree newdecl, tree olddecl)
{
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl);
- SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
+ COPY_DECL_RTL (newdecl, olddecl);
}
if (! types_match || new_defines_function)
{
@@ -1868,7 +1917,7 @@ duplicate_decls (tree newdecl, tree olddecl)
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
/* If we're keeping the built-in definition, keep the rtl,
regardless of declaration matches. */
- SET_DECL_RTL (newdecl, DECL_RTL (olddecl));
+ COPY_DECL_RTL (olddecl, newdecl);
}
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
@@ -1886,30 +1935,53 @@ duplicate_decls (tree newdecl, tree olddecl)
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
- /* If either declaration has a nondefault visibility, use it. */
- if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
+ /* Warn about conflicting visibility specifications. */
+ if (DECL_VISIBILITY_SPECIFIED (olddecl)
+ && DECL_VISIBILITY_SPECIFIED (newdecl)
+ && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
+ {
+ warning (OPT_Wattributes, "%q+D: visibility attribute ignored "
+ "because it", newdecl);
+ warning (OPT_Wattributes, "%Jconflicts with previous "
+ "declaration here", olddecl);
+ }
+ /* Choose the declaration which specified visibility. */
+ if (DECL_VISIBILITY_SPECIFIED (olddecl))
{
- if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
- && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
- {
- warning ("%J'%D': visibility attribute ignored because it",
- newdecl, newdecl);
- warning ("%Jconflicts with previous declaration here", olddecl);
- }
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+ DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
+ }
+ /* Init priority used to be merged from newdecl to olddecl by the memcpy,
+ so keep this behavior. */
+ if (TREE_CODE (newdecl) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (newdecl))
+ {
+ SET_DECL_INIT_PRIORITY (olddecl, DECL_INIT_PRIORITY (newdecl));
+ DECL_HAS_INIT_PRIORITY_P (olddecl) = 1;
+ }
+
+ /* The DECL_LANG_SPECIFIC information in OLDDECL will be replaced
+ with that from NEWDECL below. */
+ if (DECL_LANG_SPECIFIC (olddecl))
+ {
+ gcc_assert (DECL_LANG_SPECIFIC (olddecl)
+ != DECL_LANG_SPECIFIC (newdecl));
+ ggc_free (DECL_LANG_SPECIFIC (olddecl));
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
- function_size = sizeof (struct tree_decl);
+ function_size = sizeof (struct tree_decl_common);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
function_size - sizeof (struct tree_common));
- if (DECL_TEMPLATE_INSTANTIATION (newdecl))
+ memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+ (char *) newdecl + sizeof (struct tree_decl_common),
+ sizeof (struct tree_function_decl) - sizeof (struct tree_decl_common));
+ if (new_template)
/* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred:
@@ -1931,21 +2003,48 @@ duplicate_decls (tree newdecl, tree olddecl)
olddecl, and not newdecl, is on the list of
instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */
- reregister_specialization (newdecl,
- DECL_TI_TEMPLATE (newdecl),
+ reregister_specialization (newdecl,
+ new_template,
olddecl);
}
else
{
+ size_t size = tree_code_size (TREE_CODE (olddecl));
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
- sizeof (struct tree_decl) - sizeof (struct tree_common)
- + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
+ sizeof (struct tree_decl_common) - sizeof (struct tree_common));
+ switch (TREE_CODE (olddecl))
+ {
+ case LABEL_DECL:
+ case VAR_DECL:
+ case RESULT_DECL:
+ case PARM_DECL:
+ case FIELD_DECL:
+ case TYPE_DECL:
+ case CONST_DECL:
+ {
+ memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+ (char *) newdecl + sizeof (struct tree_decl_common),
+ size - sizeof (struct tree_decl_common)
+ + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
+ }
+ break;
+ default:
+ memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+ (char *) newdecl + sizeof (struct tree_decl_common),
+ sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common)
+ + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
+ break;
+ }
}
-
DECL_UID (olddecl) = olddecl_uid;
if (olddecl_friend)
DECL_FRIEND_P (olddecl) = 1;
+ if (hidden_friend)
+ {
+ DECL_ANTICIPATED (olddecl) = 1;
+ DECL_HIDDEN_FRIEND_P (olddecl) = 1;
+ }
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
@@ -1954,48 +2053,20 @@ duplicate_decls (tree newdecl, tree olddecl)
/* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
so that encode_section_info has a chance to look at the new decl
flags and attributes. */
- if (DECL_RTL_SET_P (olddecl)
+ if (DECL_RTL_SET_P (olddecl)
&& (TREE_CODE (olddecl) == FUNCTION_DECL
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
- make_decl_rtl (olddecl, NULL);
+ make_decl_rtl (olddecl);
+
+ /* The NEWDECL will no longer be needed. Because every out-of-class
+ declaration of a member results in a call to duplicate_decls,
+ freeing these nodes represents in a significant savings. */
+ ggc_free (newdecl);
return olddecl;
}
-/* Generate an implicit declaration for identifier FUNCTIONID
- as a function of type int (). Print a warning if appropriate. */
-
-tree
-implicitly_declare (tree functionid)
-{
- tree decl;
-
- /* We used to reuse an old implicit decl here,
- but this loses with inline functions because it can clobber
- the saved decl chains. */
- decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type);
-
- DECL_EXTERNAL (decl) = 1;
- TREE_PUBLIC (decl) = 1;
-
- /* ISO standard says implicit declarations are in the innermost block.
- So we record the decl in the standard fashion. */
- pushdecl (decl);
- rest_of_decl_compilation (decl, NULL, 0, 0);
-
- if (warn_implicit
- /* Only one warning per identifier. */
- && IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE)
- {
- pedwarn ("implicit declaration of function `%#D'", decl);
- }
-
- SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
-
- return decl;
-}
-
/* Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
@@ -2011,38 +2082,39 @@ redeclaration_error_message (tree newdecl, tree olddecl)
constructs like "typedef struct foo { ... } foo"
would look like an erroneous redeclaration. */
if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
- return 0;
+ return NULL;
else
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* If this is a pure function, its olddecl will actually be
the original initialization to `0' (which we force to call
abort()). Don't complain about redefinition in this case. */
- if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl))
- return 0;
+ if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl)
+ && DECL_INITIAL (olddecl) == NULL_TREE)
+ return NULL;
/* If both functions come from different namespaces, this is not
a redeclaration - this is a conflict with a used function. */
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)
&& ! decls_match (olddecl, newdecl))
- return "`%D' conflicts with used function";
+ return "%qD conflicts with used function";
/* We'll complain about linkage mismatches in
- warn_extern_redeclared_static. */
+ warn_extern_redeclared_static. */
/* Defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
- return "`%#D' not declared in class";
+ return "%q#D not declared in class";
else
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
}
- return 0;
+ return NULL;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
@@ -2052,12 +2124,12 @@ redeclaration_error_message (tree newdecl, tree olddecl)
{
if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
&& COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
return NULL;
}
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
- || (DECL_TEMPLATE_RESULT (newdecl)
+ || (DECL_TEMPLATE_RESULT (newdecl)
== DECL_TEMPLATE_RESULT (olddecl)))
return NULL;
@@ -2068,18 +2140,33 @@ redeclaration_error_message (tree newdecl, tree olddecl)
if (DECL_TEMPLATE_INFO (ot))
ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
return NULL;
}
+ else if (TREE_CODE (newdecl) == VAR_DECL
+ && DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)
+ && (! DECL_LANG_SPECIFIC (olddecl)
+ || ! CP_DECL_THREADPRIVATE_P (olddecl)
+ || DECL_THREAD_LOCAL_P (newdecl)))
+ {
+ /* Only variables can be thread-local, and all declarations must
+ agree on this property. */
+ if (DECL_THREAD_LOCAL_P (newdecl))
+ return "thread-local declaration of %q#D follows "
+ "non-thread-local declaration";
+ else
+ return "non-thread-local declaration of %q#D follows "
+ "thread-local declaration";
+ }
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
/* Objects declared at top level: */
/* If at least one is a reference, it's ok. */
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
- return 0;
+ return NULL;
/* Reject two definitions. */
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
}
else
{
@@ -2087,16 +2174,35 @@ redeclaration_error_message (tree newdecl, tree olddecl)
/* Reject two definitions, and reject a definition
together with an external reference. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
- return "redeclaration of `%#D'";
- return 0;
+ return "redeclaration of %q#D";
+ return NULL;
}
}
+/* Hash and equality functions for the named_label table. */
+
+static hashval_t
+named_label_entry_hash (const void *data)
+{
+ const struct named_label_entry *ent = (const struct named_label_entry *) data;
+ return DECL_UID (ent->label_decl);
+}
+
+static int
+named_label_entry_eq (const void *a, const void *b)
+{
+ const struct named_label_entry *ent_a = (const struct named_label_entry *) a;
+ const struct named_label_entry *ent_b = (const struct named_label_entry *) b;
+ return ent_a->label_decl == ent_b->label_decl;
+}
+
/* Create a new label, named ID. */
static tree
make_label_decl (tree id, int local_p)
{
+ struct named_label_entry *ent;
+ void **slot;
tree decl;
decl = build_decl (LABEL_DECL, id, void_type_node);
@@ -2112,30 +2218,22 @@ make_label_decl (tree id, int local_p)
/* Record the fact that this identifier is bound to this label. */
SET_IDENTIFIER_LABEL_VALUE (id, decl);
- return decl;
-}
+ /* Create the label htab for the function on demand. */
+ if (!named_labels)
+ named_labels = htab_create_ggc (13, named_label_entry_hash,
+ named_label_entry_eq, NULL);
-/* Record this label on the list of used labels so that we can check
- at the end of the function to see whether or not the label was
- actually defined, and so we can check when the label is defined whether
- this use is valid. */
+ /* Record this label on the list of labels used in this function.
+ We do this before calling make_label_decl so that we get the
+ IDENTIFIER_LABEL_VALUE before the new label is declared. */
+ ent = GGC_CNEW (struct named_label_entry);
+ ent->label_decl = decl;
-static void
-use_label (tree decl)
-{
- if (named_label_uses == NULL
- || named_label_uses->names_in_scope != current_binding_level->names
- || named_label_uses->label_decl != decl)
- {
- struct named_label_use_list *new_ent;
- new_ent = ggc_alloc (sizeof (struct named_label_use_list));
- new_ent->label_decl = decl;
- new_ent->names_in_scope = current_binding_level->names;
- new_ent->binding_level = current_binding_level;
- new_ent->o_goto_locus = input_location;
- new_ent->next = named_label_uses;
- named_label_uses = new_ent;
- }
+ slot = htab_find_slot (named_labels, ent, INSERT);
+ gcc_assert (*slot == NULL);
+ *slot = ent;
+
+ return decl;
}
/* Look for a label named ID in the current function. If one cannot
@@ -2146,14 +2244,12 @@ tree
lookup_label (tree id)
{
tree decl;
- struct named_label_list *ent;
timevar_push (TV_NAME_LOOKUP);
/* You can't use labels at global scope. */
if (current_function_decl == NULL_TREE)
{
- error ("label `%s' referenced outside of any function",
- IDENTIFIER_POINTER (id));
+ error ("label %qE referenced outside of any function", id);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
@@ -2162,20 +2258,7 @@ lookup_label (tree id)
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
- /* Record this label on the list of labels used in this function.
- We do this before calling make_label_decl so that we get the
- IDENTIFIER_LABEL_VALUE before the new label is declared. */
- ent = ggc_alloc_cleared (sizeof (struct named_label_list));
- ent->old_value = IDENTIFIER_LABEL_VALUE (id);
- ent->next = named_labels;
- named_labels = ent;
-
- /* We need a new label. */
decl = make_label_decl (id, /*local_p=*/0);
-
- /* Now fill in the information we didn't have before. */
- ent->label_decl = decl;
-
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
@@ -2184,18 +2267,16 @@ lookup_label (tree id)
tree
declare_local_label (tree id)
{
- tree decl;
+ tree decl, shadow;
/* Add a new entry to the SHADOWED_LABELS list so that when we leave
- this scope we can restore the old value of
- IDENTIFIER_TYPE_VALUE. */
- current_binding_level->shadowed_labels
- = tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
- current_binding_level->shadowed_labels);
- /* Look for the label. */
+ this scope we can restore the old value of IDENTIFIER_TYPE_VALUE. */
+ shadow = tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
+ current_binding_level->shadowed_labels);
+ current_binding_level->shadowed_labels = shadow;
+
decl = make_label_decl (id, /*local_p=*/1);
- /* Now fill in the information we didn't have before. */
- TREE_VALUE (current_binding_level->shadowed_labels) = decl;
+ TREE_VALUE (shadow) = decl;
return decl;
}
@@ -2206,125 +2287,119 @@ declare_local_label (tree id)
static int
decl_jump_unsafe (tree decl)
{
- if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
+ if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)
+ || TREE_TYPE (decl) == error_mark_node)
return 0;
- if (DECL_INITIAL (decl) == NULL_TREE
- && pod_type_p (TREE_TYPE (decl)))
+ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+ || DECL_NONTRIVIALLY_INITIALIZED_P (decl))
+ return 2;
+
+ if (pod_type_p (TREE_TYPE (decl)))
return 0;
- /* This is really only important if we're crossing an initialization.
- The POD stuff is just pedantry; why should it matter if the class
+ /* The POD stuff is just pedantry; why should it matter if the class
contains a field of pointer to member type? */
- if (DECL_INITIAL (decl)
- || (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
- return 2;
return 1;
}
+/* A subroutine of check_previous_goto_1 to identify a branch to the user. */
+
+static void
+identify_goto (tree decl, const location_t *locus)
+{
+ if (decl)
+ pedwarn ("jump to label %qD", decl);
+ else
+ pedwarn ("jump to case label");
+ if (locus)
+ pedwarn ("%H from here", locus);
+}
+
/* Check that a single previously seen jump to a newly defined label
is OK. DECL is the LABEL_DECL or 0; LEVEL is the binding_level for
the jump context; NAMES are the names in scope in LEVEL at the jump
- context; FILE and LINE are the source position of the jump or 0. */
+ context; LOCUS is the source position of the jump or 0. Returns
+ true if all is well. */
-static void
-check_previous_goto_1 (tree decl,
- struct cp_binding_level* level,
- tree names, const location_t *locus)
-{
- int identified = 0;
- int saw_eh = 0;
- struct cp_binding_level *b = current_binding_level;
- for (; b; b = b->level_chain)
- {
- tree new_decls = b->names;
- tree old_decls = (b == level ? names : NULL_TREE);
- for (; new_decls != old_decls;
+static bool
+check_previous_goto_1 (tree decl, struct cp_binding_level* level, tree names,
+ bool exited_omp, const location_t *locus)
+{
+ struct cp_binding_level *b;
+ bool identified = false, saw_eh = false, saw_omp = false;
+
+ if (exited_omp)
+ {
+ identify_goto (decl, locus);
+ error (" exits OpenMP structured block");
+ identified = saw_omp = true;
+ }
+
+ for (b = current_binding_level; b ; b = b->level_chain)
+ {
+ tree new_decls, old_decls = (b == level ? names : NULL_TREE);
+
+ for (new_decls = b->names; new_decls != old_decls;
new_decls = TREE_CHAIN (new_decls))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
continue;
- if (! identified)
+ if (!identified)
{
- if (decl)
- pedwarn ("jump to label `%D'", decl);
- else
- pedwarn ("jump to case label");
-
- if (locus)
- pedwarn ("%H from here", locus);
- identified = 1;
+ identify_goto (decl, locus);
+ identified = true;
}
-
if (problem > 1)
- cp_error_at (" crosses initialization of `%#D'",
- new_decls);
+ error (" crosses initialization of %q+#D", new_decls);
else
- cp_pedwarn_at (" enters scope of non-POD `%#D'",
- new_decls);
+ pedwarn (" enters scope of non-POD %q+#D", new_decls);
}
if (b == level)
break;
- if ((b->kind == sk_try || b->kind == sk_catch) && ! saw_eh)
+ if ((b->kind == sk_try || b->kind == sk_catch) && !saw_eh)
{
- if (! identified)
+ if (!identified)
{
- if (decl)
- pedwarn ("jump to label `%D'", decl);
- else
- pedwarn ("jump to case label");
-
- if (locus)
- pedwarn ("%H from here", locus);
- identified = 1;
+ identify_goto (decl, locus);
+ identified = true;
}
if (b->kind == sk_try)
error (" enters try block");
else
error (" enters catch block");
- saw_eh = 1;
+ saw_eh = true;
+ }
+ if (b->kind == sk_omp && !saw_omp)
+ {
+ if (!identified)
+ {
+ identify_goto (decl, locus);
+ identified = true;
+ }
+ error (" enters OpenMP structured block");
+ saw_omp = true;
}
}
-}
-static void
-check_previous_goto (struct named_label_use_list* use)
-{
- check_previous_goto_1 (use->label_decl, use->binding_level,
- use->names_in_scope, &use->o_goto_locus);
+ return !identified;
}
static void
-check_switch_goto (struct cp_binding_level* level)
+check_previous_goto (tree decl, struct named_label_use_entry *use)
{
- check_previous_goto_1 (NULL_TREE, level, level->names, NULL);
+ check_previous_goto_1 (decl, use->binding_level,
+ use->names_in_scope, use->in_omp_scope,
+ &use->o_goto_locus);
}
-/* Check that any previously seen jumps to a newly defined label DECL
- are OK. Called by define_label. */
-
-static void
-check_previous_gotos (tree decl)
+static bool
+check_switch_goto (struct cp_binding_level* level)
{
- struct named_label_use_list **usep;
-
- if (! TREE_USED (decl))
- return;
-
- for (usep = &named_label_uses; *usep; )
- {
- struct named_label_use_list *use = *usep;
- if (use->label_decl == decl)
- {
- check_previous_goto (use);
- *usep = use->next;
- }
- else
- usep = &(use->next);
- }
+ return check_previous_goto_1 (NULL_TREE, level, level->names, false, NULL);
}
/* Check that a new jump to a label DECL is OK. Called by
@@ -2333,57 +2408,114 @@ check_previous_gotos (tree decl)
void
check_goto (tree decl)
{
- int identified = 0;
+ struct named_label_entry *ent, dummy;
+ bool saw_catch = false, identified = false;
tree bad;
- struct named_label_list *lab;
- /* We can't know where a computed goto is jumping. So we assume
- that it's OK. */
- if (! DECL_P (decl))
+ /* We can't know where a computed goto is jumping.
+ So we assume that it's OK. */
+ if (TREE_CODE (decl) != LABEL_DECL)
+ return;
+
+ /* We didn't record any information about this label when we created it,
+ and there's not much point since it's trivial to analyze as a return. */
+ if (decl == cdtor_label)
return;
+ dummy.label_decl = decl;
+ ent = (struct named_label_entry *) htab_find (named_labels, &dummy);
+ gcc_assert (ent != NULL);
+
/* If the label hasn't been defined yet, defer checking. */
if (! DECL_INITIAL (decl))
{
- use_label (decl);
- return;
- }
+ struct named_label_use_entry *new_use;
- for (lab = named_labels; lab; lab = lab->next)
- if (decl == lab->label_decl)
- break;
+ /* Don't bother creating another use if the last goto had the
+ same data, and will therefore create the same set of errors. */
+ if (ent->uses
+ && ent->uses->names_in_scope == current_binding_level->names)
+ return;
- /* If the label is not on named_labels it's a gcc local label, so
- it must be in an outer scope, so jumping to it is always OK. */
- if (lab == 0)
- return;
+ new_use = GGC_NEW (struct named_label_use_entry);
+ new_use->binding_level = current_binding_level;
+ new_use->names_in_scope = current_binding_level->names;
+ new_use->o_goto_locus = input_location;
+ new_use->in_omp_scope = false;
+
+ new_use->next = ent->uses;
+ ent->uses = new_use;
+ return;
+ }
- if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls)
- && !identified)
+ if (ent->in_try_scope || ent->in_catch_scope
+ || ent->in_omp_scope || ent->bad_decls)
{
- cp_pedwarn_at ("jump to label `%D'", decl);
+ pedwarn ("jump to label %q+D", decl);
pedwarn (" from here");
- identified = 1;
+ identified = true;
}
- for (bad = lab->bad_decls; bad; bad = TREE_CHAIN (bad))
+ for (bad = ent->bad_decls; bad; bad = TREE_CHAIN (bad))
{
tree b = TREE_VALUE (bad);
int u = decl_jump_unsafe (b);
if (u > 1 && DECL_ARTIFICIAL (b))
- /* Can't skip init of __exception_info. */
- error ("%J enters catch block", b);
+ {
+ /* Can't skip init of __exception_info. */
+ error ("%J enters catch block", b);
+ saw_catch = true;
+ }
else if (u > 1)
- cp_error_at (" skips initialization of `%#D'", b);
+ error (" skips initialization of %q+#D", b);
else
- cp_pedwarn_at (" enters scope of non-POD `%#D'", b);
+ pedwarn (" enters scope of non-POD %q+#D", b);
}
- if (lab->in_try_scope)
+ if (ent->in_try_scope)
error (" enters try block");
- else if (lab->in_catch_scope)
+ else if (ent->in_catch_scope && !saw_catch)
error (" enters catch block");
+
+ if (ent->in_omp_scope)
+ error (" enters OpenMP structured block");
+ else if (flag_openmp)
+ {
+ struct cp_binding_level *b;
+ for (b = current_binding_level; b ; b = b->level_chain)
+ {
+ if (b == ent->binding_level)
+ break;
+ if (b->kind == sk_omp)
+ {
+ if (!identified)
+ {
+ pedwarn ("jump to label %q+D", decl);
+ pedwarn (" from here");
+ identified = true;
+ }
+ error (" exits OpenMP structured block");
+ break;
+ }
+ }
+ }
+}
+
+/* Check that a return is ok wrt OpenMP structured blocks.
+ Called by finish_return_stmt. Returns true if all is well. */
+
+bool
+check_omp_return (void)
+{
+ struct cp_binding_level *b;
+ for (b = current_binding_level; b ; b = b->level_chain)
+ if (b->kind == sk_omp)
+ {
+ error ("invalid exit from OpenMP structured block");
+ return false;
+ }
+ return true;
}
/* Define a label, specifying the location in the source file.
@@ -2392,19 +2524,22 @@ check_goto (tree decl)
tree
define_label (location_t location, tree name)
{
- tree decl = lookup_label (name);
- struct named_label_list *ent;
+ struct named_label_entry *ent, dummy;
struct cp_binding_level *p;
+ tree decl;
timevar_push (TV_NAME_LOOKUP);
- for (ent = named_labels; ent; ent = ent->next)
- if (ent->label_decl == decl)
- break;
+
+ decl = lookup_label (name);
+
+ dummy.label_decl = decl;
+ ent = (struct named_label_entry *) htab_find (named_labels, &dummy);
+ gcc_assert (ent != NULL);
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
- for (p = current_binding_level;
- p->kind != sk_function_parms;
+ for (p = current_binding_level;
+ p->kind != sk_function_parms;
p = p->level_chain)
p->more_cleanups_ok = 0;
@@ -2412,23 +2547,28 @@ define_label (location_t location, tree name)
pedwarn ("label named wchar_t");
if (DECL_INITIAL (decl) != NULL_TREE)
- error ("duplicate label `%D'", decl);
+ {
+ error ("duplicate label %qD", decl);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ }
else
{
+ struct named_label_use_entry *use;
+
/* Mark label as having been defined. */
DECL_INITIAL (decl) = error_mark_node;
/* Say where in the source. */
DECL_SOURCE_LOCATION (decl) = location;
- if (ent)
- {
- ent->names_in_scope = current_binding_level->names;
- ent->binding_level = current_binding_level;
- }
- check_previous_gotos (decl);
+
+ ent->binding_level = current_binding_level;
+ ent->names_in_scope = current_binding_level->names;
+
+ for (use = ent->uses; use ; use = use->next)
+ check_previous_goto (decl, use);
+ ent->uses = NULL;
}
- timevar_pop (TV_NAME_LOOKUP);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
struct cp_switch
@@ -2459,7 +2599,7 @@ static struct cp_switch *switch_stack;
void
push_switch (tree switch_stmt)
{
- struct cp_switch *p = xmalloc (sizeof (struct cp_switch));
+ struct cp_switch *p = XNEW (struct cp_switch);
p->level = current_binding_level;
p->next = switch_stack;
p->switch_stmt = switch_stmt;
@@ -2470,9 +2610,19 @@ push_switch (tree switch_stmt)
void
pop_switch (void)
{
- struct cp_switch *cs;
+ struct cp_switch *cs = switch_stack;
+ location_t switch_location;
+
+ /* Emit warnings as needed. */
+ if (EXPR_HAS_LOCATION (cs->switch_stmt))
+ switch_location = EXPR_LOCATION (cs->switch_stmt);
+ else
+ switch_location = input_location;
+ if (!processing_template_decl)
+ c_do_switch_warnings (cs->cases, switch_location,
+ SWITCH_STMT_TYPE (cs->switch_stmt),
+ SWITCH_STMT_COND (cs->switch_stmt));
- cs = switch_stack;
splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
free (cs);
@@ -2498,18 +2648,20 @@ finish_case_label (tree low_value, tree high_value)
}
/* Find the condition on which this switch statement depends. */
- cond = SWITCH_COND (switch_stack->switch_stmt);
+ cond = SWITCH_STMT_COND (switch_stack->switch_stmt);
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
- r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
+ if (!check_switch_goto (switch_stack->level))
+ return error_mark_node;
- check_switch_goto (switch_stack->level);
+ r = c_add_case_label (switch_stack->cases, cond, TREE_TYPE (cond),
+ low_value, high_value);
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
- for (p = current_binding_level;
- p->kind != sk_function_parms;
+ for (p = current_binding_level;
+ p->kind != sk_function_parms;
p = p->level_chain)
p->more_cleanups_ok = 0;
@@ -2530,85 +2682,105 @@ typename_hash (const void* k)
return hash;
}
+typedef struct typename_info {
+ tree scope;
+ tree name;
+ tree template_id;
+ bool enum_p;
+ bool class_p;
+} typename_info;
+
/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
static int
typename_compare (const void * k1, const void * k2)
{
tree t1;
- tree t2;
- tree d1;
- tree d2;
+ const typename_info *t2;
t1 = (tree) k1;
- t2 = (tree) k2;
- d1 = TYPE_NAME (t1);
- d2 = TYPE_NAME (t2);
+ t2 = (const typename_info *) k2;
- return (DECL_NAME (d1) == DECL_NAME (d2)
- && TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2)
- && ((TREE_TYPE (t1) != NULL_TREE)
- == (TREE_TYPE (t2) != NULL_TREE))
- && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
- && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
+ return (DECL_NAME (TYPE_NAME (t1)) == t2->name
+ && TYPE_CONTEXT (t1) == t2->scope
+ && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
+ && TYPENAME_IS_ENUM_P (t1) == t2->enum_p
+ && TYPENAME_IS_CLASS_P (t1) == t2->class_p);
}
/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is
- the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE
- is non-NULL, this type is being created by the implicit typename
- extension, and BASE_TYPE is a type named `t' in some base class of
- `T' which depends on template parameters.
+ the type of `T', NAME is the IDENTIFIER_NODE for `t'.
Returns the new TYPENAME_TYPE. */
static GTY ((param_is (union tree_node))) htab_t typename_htab;
static tree
-build_typename_type (tree context, tree name, tree fullname)
+build_typename_type (tree context, tree name, tree fullname,
+ enum tag_types tag_type)
{
tree t;
tree d;
+ typename_info ti;
void **e;
+ hashval_t hash;
if (typename_htab == NULL)
- {
- typename_htab = htab_create_ggc (61, &typename_hash,
- &typename_compare, NULL);
- }
-
- /* Build the TYPENAME_TYPE. */
- t = make_aggr_type (TYPENAME_TYPE);
- TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- TYPENAME_TYPE_FULLNAME (t) = fullname;
-
- /* Build the corresponding TYPE_DECL. */
- d = build_decl (TYPE_DECL, name, t);
- TYPE_NAME (TREE_TYPE (d)) = d;
- TYPE_STUB_DECL (TREE_TYPE (d)) = d;
- DECL_CONTEXT (d) = FROB_CONTEXT (context);
- DECL_ARTIFICIAL (d) = 1;
+ typename_htab = htab_create_ggc (61, &typename_hash,
+ &typename_compare, NULL);
+
+ ti.scope = FROB_CONTEXT (context);
+ ti.name = name;
+ ti.template_id = fullname;
+ ti.enum_p = tag_type == enum_type;
+ ti.class_p = (tag_type == class_type
+ || tag_type == record_type
+ || tag_type == union_type);
+ hash = (htab_hash_pointer (ti.scope)
+ ^ htab_hash_pointer (ti.name));
/* See if we already have this type. */
- e = htab_find_slot (typename_htab, t, INSERT);
+ e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
if (*e)
t = (tree) *e;
else
- *e = t;
+ {
+ /* Build the TYPENAME_TYPE. */
+ t = make_aggr_type (TYPENAME_TYPE);
+ TYPE_CONTEXT (t) = ti.scope;
+ TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
+ TYPENAME_IS_ENUM_P (t) = ti.enum_p;
+ TYPENAME_IS_CLASS_P (t) = ti.class_p;
+
+ /* Build the corresponding TYPE_DECL. */
+ d = build_decl (TYPE_DECL, name, t);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ DECL_ARTIFICIAL (d) = 1;
+
+ /* Store it in the hash table. */
+ *e = t;
+ }
return t;
}
-/* Resolve `typename CONTEXT::NAME'. Returns an appropriate type,
- unless an error occurs, in which case error_mark_node is returned.
- If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
- set, we return that, rather than the _TYPE it corresponds to, in
- other cases we look through the type decl. If TF_ERROR is set,
- complain about errors, otherwise be quiet. */
+/* Resolve `typename CONTEXT::NAME'. TAG_TYPE indicates the tag
+ provided to name the type. Returns an appropriate type, unless an
+ error occurs, in which case error_mark_node is returned. If we
+ locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
+ return that, rather than the _TYPE it corresponds to, in other
+ cases we look through the type decl. If TF_ERROR is set, complain
+ about errors, otherwise be quiet. */
tree
-make_typename_type (tree context, tree name, tsubst_flags_t complain)
+make_typename_type (tree context, tree name, enum tag_types tag_type,
+ tsubst_flags_t complain)
{
tree fullname;
+ tree t;
+ bool want_template;
if (name == error_mark_node
|| context == NULL_TREE
@@ -2637,92 +2809,88 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
name = TREE_OPERAND (name, 0);
if (TREE_CODE (name) == TEMPLATE_DECL)
name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
+ else if (TREE_CODE (name) == OVERLOAD)
+ {
+ error ("%qD is not a type", name);
+ return error_mark_node;
+ }
}
if (TREE_CODE (name) == TEMPLATE_DECL)
{
- error ("`%D' used without template parameters", name);
+ error ("%qD used without template parameters", name);
return error_mark_node;
}
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030802);
- my_friendly_assert (TYPE_P (context), 20050905);
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+ gcc_assert (TYPE_P (context));
- if (!dependent_type_p (context)
- || currently_open_class (context))
- {
- if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
- {
- tree tmpl = NULL_TREE;
- if (IS_AGGR_TYPE (context))
- tmpl = lookup_field (context, name, 0, false);
- if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
- {
- if (complain & tf_error)
- error ("no class template named `%#T' in `%#T'",
- name, context);
- return error_mark_node;
- }
-
- if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
+ /* When the CONTEXT is a dependent type, NAME could refer to a
+ dependent base class of CONTEXT. So we cannot peek inside it,
+ even if CONTEXT is a currently open scope. */
+ if (dependent_type_p (context))
+ return build_typename_type (context, name, fullname, tag_type);
- return lookup_template_class (tmpl,
- TREE_OPERAND (fullname, 1),
- NULL_TREE, context,
- /*entering_scope=*/0,
- tf_error | tf_warning | tf_user);
- }
- else
- {
- tree t;
-
- if (!IS_AGGR_TYPE (context))
- {
- if (complain & tf_error)
- error ("no type named `%#T' in `%#T'", name, context);
- return error_mark_node;
- }
-
- t = lookup_field (context, name, 0, true);
- if (t)
- {
- if (TREE_CODE (t) != TYPE_DECL)
- {
- if (complain & tf_error)
- error ("no type named `%#T' in `%#T'", name, context);
- return error_mark_node;
- }
-
- if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), t);
-
- if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
- t = TREE_TYPE (t);
-
- return t;
- }
- }
+ if (!IS_AGGR_TYPE (context))
+ {
+ if (complain & tf_error)
+ error ("%q#T is not a class", context);
+ return error_mark_node;
}
-
- /* If the CONTEXT is not a template type, then either the field is
- there now or its never going to be. */
- if (!dependent_type_p (context))
+
+ want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
+
+ /* We should only set WANT_TYPE when we're a nested typename type.
+ Then we can give better diagnostics if we find a non-type. */
+ t = lookup_field (context, name, 0, /*want_type=*/true);
+ if (!t)
{
if (complain & tf_error)
- error ("no type named `%#T' in `%#T'", name, context);
+ error (want_template ? "no class template named %q#T in %q#T"
+ : "no type named %q#T in %q#T", name, context);
return error_mark_node;
}
-
- return build_typename_type (context, name, fullname);
+
+ if (want_template && !DECL_CLASS_TEMPLATE_P (t))
+ {
+ if (complain & tf_error)
+ error ("%<typename %T::%D%> names %q#T, which is not a class template",
+ context, name, t);
+ return error_mark_node;
+ }
+ if (!want_template && TREE_CODE (t) != TYPE_DECL)
+ {
+ if (complain & tf_error)
+ error ("%<typename %T::%D%> names %q#T, which is not a type",
+ context, name, t);
+ return error_mark_node;
+ }
+
+ if (complain & tf_error)
+ perform_or_defer_access_check (TYPE_BINFO (context), t, t);
+
+ if (want_template)
+ return lookup_template_class (t, TREE_OPERAND (fullname, 1),
+ NULL_TREE, context,
+ /*entering_scope=*/0,
+ tf_warning_or_error | tf_user);
+
+ if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
+ t = TREE_TYPE (t);
+
+ return t;
}
-/* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
- unless an error occurs, in which case error_mark_node is returned.
- If we locate a TYPE_DECL, we return that, rather than the _TYPE it
- corresponds to. If COMPLAIN zero, don't complain about any errors
- that occur. */
+/* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name
+ can be resolved or an UNBOUND_CLASS_TEMPLATE, unless an error occurs,
+ in which case error_mark_node is returned.
+
+ If PARM_LIST is non-NULL, also make sure that the template parameter
+ list of TEMPLATE_DECL matches.
+
+ If COMPLAIN zero, don't complain about any errors that occur. */
tree
-make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
+make_unbound_class_template (tree context, tree name, tree parm_list,
+ tsubst_flags_t complain)
{
tree t;
tree d;
@@ -2731,8 +2899,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
name = TYPE_IDENTIFIER (name);
else if (DECL_P (name))
name = DECL_NAME (name);
- if (TREE_CODE (name) != IDENTIFIER_NODE)
- abort ();
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
if (!dependent_type_p (context)
|| currently_open_class (context))
@@ -2745,12 +2912,23 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
- error ("no class template named `%#T' in `%#T'", name, context);
+ error ("no class template named %q#T in %q#T", name, context);
+ return error_mark_node;
+ }
+
+ if (parm_list
+ && !comp_template_parms (DECL_TEMPLATE_PARMS (tmpl), parm_list))
+ {
+ if (complain & tf_error)
+ {
+ error ("template parameters do not match template");
+ error ("%q+D declared here", tmpl);
+ }
return error_mark_node;
}
-
+
if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
+ perform_or_defer_access_check (TYPE_BINFO (context), tmpl, tmpl);
return tmpl;
}
@@ -2766,33 +2944,22 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
DECL_ARTIFICIAL (d) = 1;
+ DECL_TEMPLATE_PARMS (d) = parm_list;
return t;
}
-/* A chain of TYPE_DECLs for the builtin types. */
-
-static GTY(()) tree builtin_type_decls;
-
-/* Return a chain of TYPE_DECLs for the builtin types. */
-
-tree
-cxx_builtin_type_decls (void)
-{
- return builtin_type_decls;
-}
-
/* Push the declarations of builtin types into the namespace.
RID_INDEX is the index of the builtin type in the array
RID_POINTERS. NAME is the name used when looking up the builtin
type. TYPE is the _TYPE node for the builtin type. */
void
-record_builtin_type (enum rid rid_index,
- const char* name,
- tree type)
+record_builtin_type (enum rid rid_index,
+ const char* name,
+ tree type)
{
tree rname = NULL_TREE, tname = NULL_TREE;
tree tdecl = NULL_TREE;
@@ -2827,10 +2994,7 @@ record_builtin_type (enum rid rid_index,
TYPE_NAME (type) = tdecl;
if (tdecl)
- {
- TREE_CHAIN (tdecl) = builtin_type_decls;
- builtin_type_decls = tdecl;
- }
+ debug_hooks->type_decl (tdecl, 0);
}
/* Record one of the standard Java types.
@@ -2882,7 +3046,7 @@ record_unknown_type (tree type, const char* name)
TYPE_MODE (type) = TYPE_MODE (void_type_node);
}
-/* An string for which we should create an IDENTIFIER_NODE at
+/* A string for which we should create an IDENTIFIER_NODE at
startup. */
typedef struct predefined_identifier
@@ -2907,13 +3071,15 @@ initialize_predefined_identifiers (void)
{ "C++", &lang_name_cplusplus, 0 },
{ "C", &lang_name_c, 0 },
{ "Java", &lang_name_java, 0 },
- { CTOR_NAME, &ctor_identifier, 1 },
- { "__base_ctor", &base_ctor_identifier, 1 },
- { "__comp_ctor", &complete_ctor_identifier, 1 },
- { DTOR_NAME, &dtor_identifier, 1 },
- { "__comp_dtor", &complete_dtor_identifier, 1 },
- { "__base_dtor", &base_dtor_identifier, 1 },
- { "__deleting_dtor", &deleting_dtor_identifier, 1 },
+ /* Some of these names have a trailing space so that it is
+ impossible for them to conflict with names written by users. */
+ { "__ct ", &ctor_identifier, 1 },
+ { "__base_ctor ", &base_ctor_identifier, 1 },
+ { "__comp_ctor ", &complete_ctor_identifier, 1 },
+ { "__dt ", &dtor_identifier, 1 },
+ { "__comp_dtor ", &complete_dtor_identifier, 1 },
+ { "__base_dtor ", &base_dtor_identifier, 1 },
+ { "__deleting_dtor ", &deleting_dtor_identifier, 1 },
{ IN_CHARGE_NAME, &in_charge_identifier, 0 },
{ "nelts", &nelts_identifier, 0 },
{ THIS_NAME, &this_identifier, 0 },
@@ -2945,21 +3111,21 @@ cxx_init_decl_processing (void)
tree void_ftype;
tree void_ftype_ptr;
+ build_common_tree_nodes (flag_signed_char, false);
+
/* Create all the identifiers we need. */
initialize_predefined_identifiers ();
- /* Fill in back-end hooks. */
- lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
-
/* Create the global variables. */
push_to_top_level ();
current_function_decl = NULL_TREE;
current_binding_level = NULL;
/* Enter the global namespace. */
- my_friendly_assert (global_namespace == NULL_TREE, 375);
+ gcc_assert (global_namespace == NULL_TREE);
global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
- void_type_node);
+ void_type_node);
+ TREE_PUBLIC (global_namespace) = 1;
begin_scope (sk_namespace, global_namespace);
current_lang_name = NULL_TREE;
@@ -2973,10 +3139,7 @@ cxx_init_decl_processing (void)
flag_no_inline = 1;
}
if (flag_inline_functions)
- {
- flag_inline_trees = 2;
- flag_inline_functions = 0;
- }
+ flag_inline_trees = 2;
/* Force minimum function alignment if using the least significant
bit of function pointers to store the virtual bit. */
@@ -2987,11 +3150,6 @@ cxx_init_decl_processing (void)
/* Initially, C. */
current_lang_name = lang_name_c;
- build_common_tree_nodes (flag_signed_char);
-
- error_mark_list = build_tree_list (error_mark_node, error_mark_node);
- TREE_TYPE (error_mark_list) = error_mark_node;
-
/* Create the `std' namespace. */
push_namespace (std_identifier);
std_node = current_namespace;
@@ -3008,10 +3166,8 @@ cxx_init_decl_processing (void)
java_char_type_node = record_builtin_java_type ("__java_char", -16);
java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1);
- integer_two_node = build_int_2 (2, 0);
- TREE_TYPE (integer_two_node) = integer_type_node;
- integer_three_node = build_int_2 (3, 0);
- TREE_TYPE (integer_three_node) = integer_type_node;
+ integer_two_node = build_int_cst (NULL_TREE, 2);
+ integer_three_node = build_int_cst (NULL_TREE, 3);
record_builtin_type (RID_BOOL, "bool", boolean_type_node);
truthvalue_type_node = boolean_type_node;
@@ -3031,7 +3187,7 @@ cxx_init_decl_processing (void)
void_ftype = build_function_type (void_type_node, void_list_node);
void_ftype_ptr = build_function_type (void_type_node,
tree_cons (NULL_TREE,
- ptr_type_node,
+ ptr_type_node,
void_list_node));
void_ftype_ptr
= build_exception_variant (void_ftype_ptr, empty_except_spec);
@@ -3091,13 +3247,13 @@ cxx_init_decl_processing (void)
bad_alloc_id = get_identifier ("bad_alloc");
bad_alloc_type_node = make_aggr_type (RECORD_TYPE);
TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
- bad_alloc_decl
+ bad_alloc_decl
= create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
DECL_CONTEXT (bad_alloc_decl) = current_namespace;
TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl;
pop_namespace ();
-
- ptr_ftype_sizetype
+
+ ptr_ftype_sizetype
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
size_type_node,
@@ -3117,7 +3273,6 @@ cxx_init_decl_processing (void)
/* Perform other language dependent initializations. */
init_class_processing ();
- init_search_processing ();
init_rtti_processing ();
if (flag_exceptions)
@@ -3130,12 +3285,8 @@ cxx_init_decl_processing (void)
start_fname_decls ();
/* Show we use EH for cleanups. */
- using_eh_for_cleanups ();
-
- /* Maintain consistency. Perhaps we should just complain if they
- say -fwritable-strings? */
- if (flag_writable_strings)
- flag_const_strings = 0;
+ if (flag_exceptions)
+ using_eh_for_cleanups ();
}
/* Generate an initializer for a function naming variable from
@@ -3156,17 +3307,17 @@ cp_fname_init (const char* name, tree *type_p)
domain = build_index_type (size_int (length));
init = build_string (length + 1, name);
}
-
+
type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
type = build_cplus_array_type (type, domain);
*type_p = type;
-
+
if (init)
TREE_TYPE (init) = type;
else
init = error_mark_node;
-
+
return init;
}
@@ -3174,7 +3325,7 @@ cp_fname_init (const char* name, tree *type_p)
decl, NAME is the initialization string and TYPE_DEP indicates whether
NAME depended on the type of the function. We make use of that to detect
__PRETTY_FUNCTION__ inside a template fn. This is being done
- lazily at the point of first use, so we musn't push the decl now. */
+ lazily at the point of first use, so we mustn't push the decl now. */
static tree
cp_make_fname_decl (tree id, int type_dep)
@@ -3185,15 +3336,17 @@ cp_make_fname_decl (tree id, int type_dep)
tree init = cp_fname_init (name, &type);
tree decl = build_decl (VAR_DECL, id, type);
+ if (name)
+ free ((char *) name);
+
/* As we're using pushdecl_with_scope, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl;
DECL_PRETTY_FUNCTION_P (decl) = type_dep;
-
+
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
- DECL_INITIAL (decl) = init;
-
+
TREE_USED (decl) = 1;
if (current_function_decl)
@@ -3201,12 +3354,13 @@ cp_make_fname_decl (tree id, int type_dep)
struct cp_binding_level *b = current_binding_level;
while (b->level_chain->kind != sk_function_parms)
b = b->level_chain;
- pushdecl_with_scope (decl, b);
- cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+ pushdecl_with_scope (decl, b, /*is_friend=*/false);
+ cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
}
else
pushdecl_top_level_and_finish (decl, init);
-
+
return decl;
}
@@ -3224,12 +3378,12 @@ cp_make_fname_decl (tree id, int type_dep)
static tree
builtin_function_1 (const char* name,
- tree type,
- tree context,
- int code,
- enum built_in_class class,
- const char* libname,
- tree attrs)
+ tree type,
+ tree context,
+ enum built_in_function code,
+ enum built_in_class class,
+ const char* libname,
+ tree attrs)
{
tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
DECL_BUILT_IN_CLASS (decl) = class;
@@ -3243,10 +3397,10 @@ builtin_function_1 (const char* name,
function in the namespace. */
if (libname)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname));
- make_decl_rtl (decl, NULL);
- /* Warn if a function in the namespace for users
- is used without an occasion to consider it declared. */
+ /* A function in the user's namespace should have an explicit
+ declaration before it is used. Mark the built-in function as
+ anticipated but not actually declared. */
if (name[0] != '_' || name[1] != '_')
DECL_ANTICIPATED (decl) = 1;
@@ -3277,23 +3431,23 @@ builtin_function_1 (const char* name,
tree
builtin_function (const char* name,
- tree type,
- int code,
- enum built_in_class class,
- const char* libname,
- tree attrs)
+ tree type,
+ int code,
+ enum built_in_class cl,
+ const char* libname,
+ tree attrs)
{
/* All builtins that don't begin with an '_' should additionally
go in the 'std' namespace. */
if (name[0] != '_')
{
push_namespace (std_identifier);
- builtin_function_1 (name, type, std_node, code, class, libname, attrs);
+ builtin_function_1 (name, type, std_node, code, cl, libname, attrs);
pop_namespace ();
}
return builtin_function_1 (name, type, NULL_TREE, code,
- class, libname, attrs);
+ cl, libname, attrs);
}
/* Generate a FUNCTION_DECL with the typical flags for a runtime library
@@ -3306,9 +3460,12 @@ build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
DECL_EXTERNAL (fn) = 1;
TREE_PUBLIC (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
- TREE_NOTHROW (fn) = 1;
SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
SET_DECL_LANGUAGE (fn, lang_c);
+ /* Runtime library routines are, by definition, available in an
+ external shared object. */
+ DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
+ DECL_VISIBILITY_SPECIFIED (fn) = 1;
return fn;
}
@@ -3319,7 +3476,9 @@ build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
tree
build_library_fn (tree name, tree type)
{
- return build_library_fn_1 (name, ERROR_MARK, type);
+ tree fn = build_library_fn_1 (name, ERROR_MARK, type);
+ TREE_NOTHROW (fn) = 1;
+ return fn;
}
/* Returns the _DECL for a library function with C++ linkage. */
@@ -3331,7 +3490,6 @@ build_cp_library_fn (tree name, enum tree_code operator_code, tree type)
TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
SET_DECL_LANGUAGE (fn, lang_cplusplus);
- set_mangled_name_for_decl (fn);
return fn;
}
@@ -3452,15 +3610,15 @@ fixup_anonymous_aggr (tree t)
type = TREE_TYPE (field);
if (CLASS_TYPE_P (type))
{
- if (TYPE_NEEDS_CONSTRUCTING (type))
- cp_error_at ("member %#D' with constructor not allowed in anonymous aggregate",
- field);
+ if (TYPE_NEEDS_CONSTRUCTING (type))
+ error ("member %q+#D with constructor not allowed "
+ "in anonymous aggregate", field);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- cp_error_at ("member %#D' with destructor not allowed in anonymous aggregate",
- field);
+ error ("member %q+#D with destructor not allowed "
+ "in anonymous aggregate", field);
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
- cp_error_at ("member %#D' with copy assignment operator not allowed in anonymous aggregate",
- field);
+ error ("member %q+#D with copy assignment operator "
+ "not allowed in anonymous aggregate", field);
}
}
}
@@ -3472,13 +3630,10 @@ fixup_anonymous_aggr (tree t)
Returns the type declared; or NULL_TREE if none. */
tree
-check_tag_decl (tree declspecs)
+check_tag_decl (cp_decl_specifier_seq *declspecs)
{
- int found_type = 0;
- int saw_friend = 0;
- int saw_typedef = 0;
- tree ob_modifier = NULL_TREE;
- tree link;
+ int saw_friend = declspecs->specs[(int)ds_friend] != 0;
+ int saw_typedef = declspecs->specs[(int)ds_typedef] != 0;
/* If a class, struct, or enum type is declared by the DECLSPECS
(i.e, if a class-specifier, enum-specifier, or non-typename
elaborated-type-specifier appears in the DECLSPECS),
@@ -3486,59 +3641,24 @@ check_tag_decl (tree declspecs)
tree declared_type = NULL_TREE;
bool error_p = false;
- for (link = declspecs; link; link = TREE_CHAIN (link))
- {
- tree value = TREE_VALUE (link);
-
- if (TYPE_P (value) || TREE_CODE (value) == TYPE_DECL
- || (TREE_CODE (value) == IDENTIFIER_NODE
- && is_typename_at_global_scope (value)))
- {
- ++found_type;
-
- if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE)
- {
- if (! in_system_header)
- pedwarn ("redeclaration of C++ built-in type `%T'", value);
- return NULL_TREE;
- }
-
- if (TYPE_P (value)
- && ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value))
- || TREE_CODE (value) == ENUMERAL_TYPE))
- {
- my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
- declared_type = value;
- }
- }
- else if (value == ridpointers[(int) RID_TYPEDEF])
- saw_typedef = 1;
- else if (value == ridpointers[(int) RID_FRIEND])
- {
- if (current_class_type == NULL_TREE
- || current_scope () != current_class_type)
- ob_modifier = value;
- else
- saw_friend = 1;
- }
- else if (value == ridpointers[(int) RID_STATIC]
- || value == ridpointers[(int) RID_EXTERN]
- || value == ridpointers[(int) RID_AUTO]
- || value == ridpointers[(int) RID_REGISTER]
- || value == ridpointers[(int) RID_INLINE]
- || value == ridpointers[(int) RID_VIRTUAL]
- || value == ridpointers[(int) RID_CONST]
- || value == ridpointers[(int) RID_VOLATILE]
- || value == ridpointers[(int) RID_EXPLICIT]
- || value == ridpointers[(int) RID_THREAD])
- ob_modifier = value;
- else if (value == error_mark_node)
- error_p = true;
- }
-
- if (found_type > 1)
+ if (declspecs->multiple_types_p)
error ("multiple types in one declaration");
+ else if (declspecs->redefined_builtin_type)
+ {
+ if (!in_system_header)
+ pedwarn ("redeclaration of C++ built-in type %qT",
+ declspecs->redefined_builtin_type);
+ return NULL_TREE;
+ }
+ if (declspecs->type
+ && TYPE_P (declspecs->type)
+ && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
+ && IS_AGGR_TYPE (declspecs->type))
+ || TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
+ declared_type = declspecs->type;
+ else if (declspecs->type == error_mark_node)
+ error_p = true;
if (declared_type == NULL_TREE && ! saw_friend && !error_p)
pedwarn ("declaration does not declare anything");
/* Check for an anonymous union. */
@@ -3546,47 +3666,56 @@ check_tag_decl (tree declspecs)
&& TYPE_ANONYMOUS_P (declared_type))
{
/* 7/3 In a simple-declaration, the optional init-declarator-list
- can be omitted only when declaring a class (clause 9) or
- enumeration (7.2), that is, when the decl-specifier-seq contains
- either a class-specifier, an elaborated-type-specifier with
- a class-key (9.1), or an enum-specifier. In these cases and
- whenever a class-specifier or enum-specifier is present in the
- decl-specifier-seq, the identifiers in these specifiers are among
- the names being declared by the declaration (as class-name,
- enum-names, or enumerators, depending on the syntax). In such
- cases, and except for the declaration of an unnamed bit-field (9.6),
- the decl-specifier-seq shall introduce one or more names into the
- program, or shall redeclare a name introduced by a previous
- declaration. [Example:
- enum { }; // ill-formed
- typedef class { }; // ill-formed
- --end example] */
+ can be omitted only when declaring a class (clause 9) or
+ enumeration (7.2), that is, when the decl-specifier-seq contains
+ either a class-specifier, an elaborated-type-specifier with
+ a class-key (9.1), or an enum-specifier. In these cases and
+ whenever a class-specifier or enum-specifier is present in the
+ decl-specifier-seq, the identifiers in these specifiers are among
+ the names being declared by the declaration (as class-name,
+ enum-names, or enumerators, depending on the syntax). In such
+ cases, and except for the declaration of an unnamed bit-field (9.6),
+ the decl-specifier-seq shall introduce one or more names into the
+ program, or shall redeclare a name introduced by a previous
+ declaration. [Example:
+ enum { }; // ill-formed
+ typedef class { }; // ill-formed
+ --end example] */
if (saw_typedef)
- {
- error ("missing type-name in typedef-declaration");
- return NULL_TREE;
- }
+ {
+ error ("missing type-name in typedef-declaration");
+ return NULL_TREE;
+ }
/* Anonymous unions are objects, so they can have specifiers. */;
SET_ANON_AGGR_TYPE_P (declared_type);
- if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
+ if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
&& !in_system_header)
pedwarn ("ISO C++ prohibits anonymous structs");
}
- else if (ob_modifier)
+ else
{
- if (ob_modifier == ridpointers[(int) RID_INLINE]
- || ob_modifier == ridpointers[(int) RID_VIRTUAL])
- error ("`%D' can only be specified for functions", ob_modifier);
- else if (ob_modifier == ridpointers[(int) RID_FRIEND])
- error ("`%D' can only be specified inside a class", ob_modifier);
- else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
- error ("`%D' can only be specified for constructors",
- ob_modifier);
- else
- error ("`%D' can only be specified for objects and functions",
- ob_modifier);
+ if (declspecs->specs[(int)ds_inline]
+ || declspecs->specs[(int)ds_virtual])
+ error ("%qs can only be specified for functions",
+ declspecs->specs[(int)ds_inline]
+ ? "inline" : "virtual");
+ else if (saw_friend
+ && (!current_class_type
+ || current_scope () != current_class_type))
+ error ("%<friend%> can only be specified inside a class");
+ else if (declspecs->specs[(int)ds_explicit])
+ error ("%<explicit%> can only be specified for constructors");
+ else if (declspecs->storage_class)
+ error ("a storage class can only be specified for objects "
+ "and functions");
+ else if (declspecs->specs[(int)ds_const]
+ || declspecs->specs[(int)ds_volatile]
+ || declspecs->specs[(int)ds_restrict]
+ || declspecs->specs[(int)ds_thread])
+ error ("qualifiers can only be specified for objects "
+ "and functions");
}
return declared_type;
@@ -3601,19 +3730,28 @@ check_tag_decl (tree declspecs)
Otherwise, it is an error.
C++: may have to grok the declspecs to learn about static,
- complain for anonymous unions.
+ complain for anonymous unions.
Returns the TYPE declared -- or NULL_TREE if none. */
tree
-shadow_tag (tree declspecs)
+shadow_tag (cp_decl_specifier_seq *declspecs)
{
tree t = check_tag_decl (declspecs);
if (!t)
return NULL_TREE;
- maybe_process_partial_specialization (t);
+ if (declspecs->attributes)
+ {
+ warning (0, "attribute ignored in declaration of %q+#T", t);
+ warning (0, "attribute for %q+#T must follow the %qs keyword",
+ t, class_key_or_enum_as_string (t));
+
+ }
+
+ if (maybe_process_partial_specialization (t) == error_mark_node)
+ return NULL_TREE;
/* This is where the variables in an anonymous union are
declared. An anonymous union declaration looks like:
@@ -3626,8 +3764,8 @@ shadow_tag (tree declspecs)
if (TYPE_FIELDS (t))
{
- tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
- NULL);
+ tree decl = grokdeclarator (/*declarator=*/NULL,
+ declspecs, NORMAL, 0, NULL);
finish_anon_union (decl);
}
}
@@ -3638,15 +3776,14 @@ shadow_tag (tree declspecs)
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
-groktypename (tree typename)
+groktypename (cp_decl_specifier_seq *type_specifiers,
+ const cp_declarator *declarator)
{
- tree specs, attrs;
+ tree attrs;
tree type;
- if (TREE_CODE (typename) != TREE_LIST)
- return typename;
- split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
- type = grokdeclarator (TREE_VALUE (typename), specs,
- TYPENAME, 0, &attrs);
+ attrs = type_specifiers->attributes;
+ type_specifiers->attributes = NULL_TREE;
+ type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
if (attrs)
cplus_decl_attributes (&type, attrs, 0);
return type;
@@ -3668,23 +3805,19 @@ groktypename (tree typename)
grokfield and not through here. */
tree
-start_decl (tree declarator,
- tree declspecs,
- int initialized,
- tree attributes,
- tree prefix_attributes)
+start_decl (const cp_declarator *declarator,
+ cp_decl_specifier_seq *declspecs,
+ int initialized,
+ tree attributes,
+ tree prefix_attributes,
+ tree *pushed_scope_p)
{
tree decl;
tree type, tem;
tree context;
+ bool was_public;
- /* This should only be done once on the top most decl. */
- if (have_extern_spec)
- {
- declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
- declspecs);
- have_extern_spec = false;
- }
+ *pushed_scope_p = NULL_TREE;
/* An object declared as __attribute__((deprecated)) suppresses
warnings of uses of other deprecated items. */
@@ -3698,27 +3831,22 @@ start_decl (tree declarator,
deprecated_state = DEPRECATED_NORMAL;
- if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
+ if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE
+ || decl == error_mark_node)
return error_mark_node;
type = TREE_TYPE (decl);
- if (type == error_mark_node)
- return error_mark_node;
-
context = DECL_CONTEXT (decl);
- if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
- && context != current_namespace && TREE_CODE (decl) == VAR_DECL)
+ if (context)
{
- /* When parsing the initializer, lookup should use the object's
- namespace. */
- push_decl_namespace (context);
- }
+ *pushed_scope_p = push_scope (context);
- /* We are only interested in class contexts, later. */
- if (context && TREE_CODE (context) == NAMESPACE_DECL)
- context = NULL_TREE;
+ /* We are only interested in class contexts, later. */
+ if (TREE_CODE (context) == NAMESPACE_DECL)
+ context = NULL_TREE;
+ }
if (initialized)
/* Is it valid for this decl to have an initializer at all?
@@ -3727,14 +3855,12 @@ start_decl (tree declarator,
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- error ("typedef `%D' is initialized (use __typeof__ instead)", decl);
- initialized = 0;
- break;
+ error ("typedef %qD is initialized (use __typeof__ instead)", decl);
+ return error_mark_node;
case FUNCTION_DECL:
- error ("function `%#D' is initialized like a variable", decl);
- initialized = 0;
- break;
+ error ("function %q#D is initialized like a variable", decl);
+ return error_mark_node;
default:
break;
@@ -3744,91 +3870,108 @@ start_decl (tree declarator,
{
if (! toplevel_bindings_p ()
&& DECL_EXTERNAL (decl))
- warning ("declaration of `%#D' has `extern' and is initialized",
- decl);
+ warning (0, "declaration of %q#D has %<extern%> and is initialized",
+ decl);
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
-
- /* Tell `pushdecl' this is an initialized decl
- even though we don't yet have the initializer expression.
- Also tell `cp_finish_decl' it may store the real initializer. */
- DECL_INITIAL (decl) = error_mark_node;
}
/* Set attributes here so if duplicate decl, will have proper attributes. */
cplus_decl_attributes (&decl, attributes, 0);
+ /* Dllimported symbols cannot be defined. Static data members (which
+ can be initialized in-class and dllimported) go through grokfield,
+ not here, so we don't need to exclude those decls when checking for
+ a definition. */
+ if (initialized && DECL_DLLIMPORT_P (decl))
+ {
+ error ("definition of %q#D is marked %<dllimport%>", decl);
+ DECL_DLLIMPORT_P (decl) = 0;
+ }
+
/* If #pragma weak was used, mark the decl weak now. */
- if (global_scope_p (current_binding_level))
- maybe_apply_pragma_weak (decl);
+ maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
- warning ("%Jinline function '%D' given attribute noinline", decl, decl);
+ warning (0, "inline function %q+D given attribute noinline", decl);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
- push_nested_class (context);
-
if (TREE_CODE (decl) == VAR_DECL)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
- error ("`%#D' is not a static member of `%#T'", decl, context);
+ error ("%q#D is not a static member of %q#T", decl, context);
else
{
if (DECL_CONTEXT (field) != context)
{
if (!same_type_p (DECL_CONTEXT (field), context))
- pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'",
+ pedwarn ("ISO C++ does not permit %<%T::%D%> "
+ "to be defined as %<%T::%D%>",
DECL_CONTEXT (field), DECL_NAME (decl),
context, DECL_NAME (decl));
DECL_CONTEXT (decl) = DECL_CONTEXT (field);
}
+ if (processing_specialization
+ && template_class_depth (context) == 0
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (context))
+ error ("template header not allowed in member definition "
+ "of explicitly specialized class");
/* Static data member are tricky; an in-class initialization
still doesn't provide a definition, so the in-class
declaration will have DECL_EXTERNAL set, but will have an
initialization. Thus, duplicate_decls won't warn
about this situation, and so we check here. */
- if (DECL_INITIAL (decl) && DECL_INITIAL (field))
- error ("duplicate initialization of %D", decl);
- if (duplicate_decls (decl, field))
+ if (initialized && DECL_INITIALIZED_IN_CLASS_P (field))
+ error ("duplicate initialization of %qD", decl);
+ if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
decl = field;
}
}
else
{
tree field = check_classfn (context, decl,
- processing_template_decl
- > template_class_depth (context));
- if (field && duplicate_decls (decl, field))
+ (processing_template_decl
+ > template_class_depth (context))
+ ? current_template_parms
+ : NULL_TREE);
+ if (field && duplicate_decls (decl, field,
+ /*newdecl_is_friend=*/false))
decl = field;
}
/* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set. */
DECL_IN_AGGR_P (decl) = 0;
- if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
- || CLASSTYPE_TEMPLATE_INSTANTIATION (context))
+ /* Do not mark DECL as an explicit specialization if it was not
+ already marked as an instantiation; a declaration should
+ never be marked as a specialization unless we know what
+ template is being specialized. */
+ if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
{
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+
/* [temp.expl.spec] An explicit specialization of a static data
member of a template is a definition if the declaration
includes an initializer; otherwise, it is a declaration.
We check for processing_specialization so this only applies
to the new specialization syntax. */
- if (DECL_INITIAL (decl) == NULL_TREE && processing_specialization)
+ if (!initialized && processing_specialization)
DECL_EXTERNAL (decl) = 1;
}
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
- pedwarn ("declaration of `%#D' outside of class is not definition",
- decl);
+ pedwarn ("declaration of %q#D outside of class is not definition",
+ decl);
}
+ was_public = TREE_PUBLIC (decl);
+
/* Enter this declaration into the symbol table. */
tem = maybe_push_decl (decl);
@@ -3837,32 +3980,48 @@ start_decl (tree declarator,
if (tem == error_mark_node)
return error_mark_node;
-#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
/* Tell the back-end to use or not use .common as appropriate. If we say
-fconserve-space, we want this to save .data space, at the expense of
wrong semantics. If we say -fno-conserve-space, we want this to
produce errors about redefs; to do this we force variables into the
data segment. */
- DECL_COMMON (tem) = ((TREE_CODE (tem) != VAR_DECL
- || !DECL_THREAD_LOCAL (tem))
- && (flag_conserve_space || ! TREE_PUBLIC (tem)));
-#endif
+ if (flag_conserve_space
+ && TREE_CODE (tem) == VAR_DECL
+ && TREE_PUBLIC (tem)
+ && !DECL_THREAD_LOCAL_P (tem)
+ && !have_global_bss_p ())
+ DECL_COMMON (tem) = 1;
- if (! processing_template_decl)
- start_decl_1 (tem);
+ if (TREE_CODE (tem) == VAR_DECL
+ && DECL_NAMESPACE_SCOPE_P (tem) && !TREE_PUBLIC (tem) && !was_public
+ && !DECL_THIS_STATIC (tem) && !DECL_ARTIFICIAL (tem))
+ {
+ /* This is a const variable with implicit 'static'. Set
+ DECL_THIS_STATIC so we can tell it from variables that are
+ !TREE_PUBLIC because of the anonymous namespace. */
+ gcc_assert (cp_type_readonly (TREE_TYPE (tem)));
+ DECL_THIS_STATIC (tem) = 1;
+ }
+
+ if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
+ start_decl_1 (tem, initialized);
return tem;
}
void
-start_decl_1 (tree decl)
+start_decl_1 (tree decl, bool initialized)
{
- tree type = TREE_TYPE (decl);
- int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+ tree type;
- if (type == error_mark_node)
+ gcc_assert (!processing_template_decl);
+
+ if (error_operand_p (decl))
return;
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ type = TREE_TYPE (decl);
+
if (initialized)
/* Is it valid for this decl to have an initializer at all?
If not, set INITIALIZED to zero, which will indirectly
@@ -3874,31 +4033,24 @@ start_decl_1 (tree decl)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
- error ("variable `%#D' has initializer but incomplete type",
- decl);
+ error ("variable %q#D has initializer but incomplete type", decl);
initialized = 0;
type = TREE_TYPE (decl) = error_mark_node;
}
else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
{
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
- error ("elements of array `%#D' have incomplete type", decl);
+ error ("elements of array %q#D have incomplete type", decl);
/* else we already gave an error in start_decl. */
initialized = 0;
}
}
-
- if (!initialized
- && TREE_CODE (decl) != TYPE_DECL
- && TREE_CODE (decl) != TEMPLATE_DECL
- && type != error_mark_node
- && IS_AGGR_TYPE (type)
- && ! DECL_EXTERNAL (decl))
+ else if (IS_AGGR_TYPE (type)
+ && ! DECL_EXTERNAL (decl))
{
- if ((! processing_template_decl || ! uses_template_parms (type))
- && !COMPLETE_TYPE_P (complete_type (type)))
+ if (!COMPLETE_TYPE_P (complete_type (type)))
{
- error ("aggregate `%#D' has incomplete type and cannot be defined",
+ error ("aggregate %q#D has incomplete type and cannot be defined",
decl);
/* Change the type so that assemble_variable will give
DECL an rtl we can live with: (mem (const_int 0)). */
@@ -3916,9 +4068,6 @@ start_decl_1 (tree decl)
}
}
- if (! initialized)
- DECL_INITIAL (decl) = NULL_TREE;
-
/* Create a new scope to hold this declaration if necessary.
Whether or not a new scope is necessary cannot be determined
until after the type has been completed; if the type is a
@@ -3948,22 +4097,20 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
if ((DECL_LANG_SPECIFIC (decl) == 0
|| DECL_IN_AGGR_P (decl) == 0)
&& ! DECL_THIS_EXTERN (decl))
- error ("`%D' declared as reference but not initialized", decl);
+ error ("%qD declared as reference but not initialized", decl);
return NULL_TREE;
}
if (TREE_CODE (init) == CONSTRUCTOR)
{
- error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl);
+ error ("ISO C++ forbids use of initializer list to "
+ "initialize reference %qD", decl);
return NULL_TREE;
}
if (TREE_CODE (init) == TREE_LIST)
init = build_x_compound_expr_from_list (init, "initializer");
- if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
- init = convert_from_reference (init);
-
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
/* Note: default conversion is only called in very special cases. */
@@ -3971,8 +4118,8 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
/* Convert INIT to the reference type TYPE. This may involve the
creation of a temporary, whose lifetime must be the same as that
- of the reference. If so, a DECL_STMT for the temporary will be
- added just after the DECL_STMT for DECL. That's why we don't set
+ of the reference. If so, a DECL_EXPR for the temporary will be
+ added just after the DECL_EXPR for DECL. That's why we don't set
DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized
first. */
@@ -3982,7 +4129,7 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
return NULL_TREE;
else if (tmp == NULL_TREE)
{
- error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init));
+ error ("cannot initialize %qT from %qT", type, TREE_TYPE (init));
return NULL_TREE;
}
@@ -3994,6 +4141,30 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
return NULL_TREE;
}
+/* Designated initializers in arrays are not supported in GNU C++.
+ The parser cannot detect this error since it does not know whether
+ a given brace-enclosed initializer is for a class type or for an
+ array. This function checks that CE does not use a designated
+ initializer. If it does, an error is issued. Returns true if CE
+ is valid, i.e., does not have a designated initializer. */
+
+static bool
+check_array_designated_initializer (const constructor_elt *ce)
+{
+ /* Designated initializers for array elements arenot supported. */
+ if (ce->index)
+ {
+ /* The parser only allows identifiers as designated
+ intializers. */
+ gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
+ error ("name %qD used in a GNU-style designated "
+ "initializer for an array", ce->index);
+ return false;
+ }
+
+ return true;
+}
+
/* When parsing `int a[] = {1, 2};' we don't know the size of the
array until we finish parsing the initializer. If that's the
situation we're in, update DECL accordingly. */
@@ -4011,27 +4182,55 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
But let's leave it here to ease the eventual merge. */
int do_default = !DECL_EXTERNAL (decl);
tree initializer = init ? init : DECL_INITIAL (decl);
- int failure = complete_array_type (type, initializer, do_default);
+ int failure = 0;
- if (failure == 1)
- error ("initializer fails to determine size of `%D'", decl);
+ /* Check that there are no designated initializers in INIT, as
+ those are not supported in GNU C++, and as the middle-end
+ will crash if presented with a non-numeric designated
+ initializer. */
+ if (initializer && TREE_CODE (initializer) == CONSTRUCTOR)
+ {
+ VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initializer);
+ constructor_elt *ce;
+ HOST_WIDE_INT i;
+ for (i = 0;
+ VEC_iterate (constructor_elt, v, i, ce);
+ ++i)
+ if (!check_array_designated_initializer (ce))
+ failure = 1;
+ }
- if (failure == 2)
+ if (!failure)
{
- if (do_default)
- error ("array size missing in `%D'", decl);
- /* If a `static' var's size isn't known, make it extern as
- well as static, so it does not get allocated. If it's not
- `static', then don't mark it extern; finish_incomplete_decl
- will give it a default size and it will get allocated. */
- else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
- DECL_EXTERNAL (decl) = 1;
+ failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
+ do_default);
+ if (failure == 1)
+ {
+ error ("initializer fails to determine size of %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
+ else if (failure == 2)
+ {
+ if (do_default)
+ {
+ error ("array size missing in %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
+ /* If a `static' var's size isn't known, make it extern as
+ well as static, so it does not get allocated. If it's not
+ `static', then don't mark it extern; finish_incomplete_decl
+ will give it a default size and it will get allocated. */
+ else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
+ DECL_EXTERNAL (decl) = 1;
+ }
+ else if (failure == 3)
+ {
+ error ("zero-size array %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
}
- if (pedantic && TYPE_DOMAIN (type) != NULL_TREE
- && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
- integer_zero_node))
- error ("zero-size array `%D'", decl);
+ cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
layout_decl (decl, 0);
}
@@ -4043,10 +4242,11 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
static void
layout_var_decl (tree decl)
{
- tree type = TREE_TYPE (decl);
-#if 0
- tree ttype = target_type (type);
-#endif
+ tree type;
+
+ type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return;
/* If we haven't already layed out this declaration, do so now.
Note that we must not call complete type for an external object
@@ -4055,10 +4255,10 @@ layout_var_decl (tree decl)
`extern X x' for some incomplete type `X'.) */
if (!DECL_EXTERNAL (decl))
complete_type (type);
- if (!DECL_SIZE (decl)
+ if (!DECL_SIZE (decl)
&& TREE_TYPE (decl) != error_mark_node
&& (COMPLETE_TYPE_P (type)
- || (TREE_CODE (type) == ARRAY_TYPE
+ || (TREE_CODE (type) == ARRAY_TYPE
&& !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))))
layout_decl (decl, 0);
@@ -4068,7 +4268,7 @@ layout_var_decl (tree decl)
/* An automatic variable with an incomplete type: that is an error.
Don't talk about array types here, since we took care of that
message in grokdeclarator. */
- error ("storage size of `%D' isn't known", decl);
+ error ("storage size of %qD isn't known", decl);
TREE_TYPE (decl) = error_mark_node;
}
#if 0
@@ -4090,14 +4290,8 @@ layout_var_decl (tree decl)
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
- error ("storage size of `%D' isn't constant", decl);
+ error ("storage size of %qD isn't constant", decl);
}
-
- if (TREE_STATIC (decl)
- && !DECL_ARTIFICIAL (decl)
- && current_function_decl
- && DECL_CONTEXT (decl) == current_function_decl)
- push_local_name (decl);
}
/* If a local static variable is declared in an inline function, or if
@@ -4115,7 +4309,7 @@ maybe_commonize_var (tree decl)
&& DECL_FUNCTION_SCOPE_P (decl)
/* Unfortunately, import_export_decl has not always been called
before the function is processed, so we cannot simply check
- DECL_COMDAT. */
+ DECL_COMDAT. */
&& (DECL_COMDAT (DECL_CONTEXT (decl))
|| ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
|| DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
@@ -4145,8 +4339,11 @@ maybe_commonize_var (tree decl)
be merged. */
TREE_PUBLIC (decl) = 0;
DECL_COMMON (decl) = 0;
- cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
- warning ("%J you can work around this by removing the initializer",
+ warning (0, "sorry: semantics of inline function static "
+ "data %q+#D are wrong (you'll wind up "
+ "with multiple copies)", decl);
+ warning (0, "%J you can work around this by removing "
+ "the initializer",
decl);
}
}
@@ -4172,9 +4369,21 @@ check_for_uninitialized_const_var (tree decl)
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
&& !DECL_INITIAL (decl))
- error ("uninitialized const `%D'", decl);
+ error ("uninitialized const %qD", decl);
}
+
+/* Structure holding the current initializer being processed by reshape_init.
+ CUR is a pointer to the current element being processed, END is a pointer
+ after the last element present in the initializer. */
+typedef struct reshape_iterator_t
+{
+ constructor_elt *cur;
+ constructor_elt *end;
+} reshape_iter;
+
+static tree reshape_init_r (tree, reshape_iter *, bool);
+
/* FIELD is a FIELD_DECL or NULL. In the former case, the value
returned is the next FIELD_DECL (possibly FIELD itself) that can be
initialized. If there are no more such fields, the return value
@@ -4192,132 +4401,204 @@ next_initializable_field (tree field)
return field;
}
-/* Subroutine of reshape_init. Reshape the constructor for an array. INITP
- is the pointer to the old constructor list (to the CONSTRUCTOR_ELTS of
- the CONSTRUCTOR we are processing), while NEW_INIT is the CONSTRUCTOR we
- are building.
- ELT_TYPE is the element type of the array. MAX_INDEX is an INTEGER_CST
- representing the size of the array minus one (the maximum index), or
- NULL_TREE if the array was declared without specifying the size. */
+/* Subroutine of reshape_init_array and reshape_init_vector, which does
+ the actual work. ELT_TYPE is the element type of the array. MAX_INDEX is an
+ INTEGER_CST representing the size of the array minus one (the maximum index),
+ or NULL_TREE if the array was declared without specifying the size. D is
+ the iterator within the constructor. */
-static bool
-reshape_init_array (tree elt_type, tree max_index,
- tree *initp, tree new_init)
+static tree
+reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
{
+ tree new_init;
bool sized_array_p = (max_index != NULL_TREE);
unsigned HOST_WIDE_INT max_index_cst = 0;
unsigned HOST_WIDE_INT index;
+ /* The initializer for an array is always a CONSTRUCTOR. */
+ new_init = build_constructor (NULL_TREE, NULL);
+
if (sized_array_p)
{
+ /* Minus 1 is used for zero sized arrays. */
+ if (integer_all_onesp (max_index))
+ return new_init;
+
if (host_integerp (max_index, 1))
max_index_cst = tree_low_cst (max_index, 1);
/* sizetype is sign extended, not zero extended. */
else
- max_index_cst = tree_low_cst (convert (size_type_node, max_index), 1);
+ max_index_cst = tree_low_cst (fold_convert (size_type_node, max_index),
+ 1);
}
/* Loop until there are no more initializers. */
for (index = 0;
- *initp && (!sized_array_p || index <= max_index_cst);
+ d->cur != d->end && (!sized_array_p || index <= max_index_cst);
++index)
{
- tree element_init;
- tree designated_index;
+ tree elt_init;
- element_init = reshape_init (elt_type, initp);
- if (element_init == error_mark_node)
- return false;
- TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
- CONSTRUCTOR_ELTS (new_init) = element_init;
- designated_index = TREE_PURPOSE (element_init);
- if (designated_index)
- {
- /* Handle array designated initializers (GNU extension). */
- if (TREE_CODE (designated_index) == IDENTIFIER_NODE)
- {
- error ("name `%D' used in a GNU-style designated "
- "initializer for an array", designated_index);
- TREE_PURPOSE (element_init) = NULL_TREE;
- }
- else
- abort ();
- }
+ check_array_designated_initializer (d->cur);
+ elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
+ if (elt_init == error_mark_node)
+ return error_mark_node;
+ CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), NULL_TREE, elt_init);
}
- return true;
+ return new_init;
}
-/* Undo the brace-elision allowed by [dcl.init.aggr] in a
- brace-enclosed aggregate initializer.
+/* Subroutine of reshape_init_r, processes the initializers for arrays.
+ Parameters are the same of reshape_init_r. */
- *INITP is one of a list of initializers describing a brace-enclosed
- initializer for an entity of the indicated aggregate TYPE. It may
- not presently match the shape of the TYPE; for example:
-
- struct S { int a; int b; };
- struct S a[] = { 1, 2, 3, 4 };
+static tree
+reshape_init_array (tree type, reshape_iter *d)
+{
+ tree max_index = NULL_TREE;
- Here *INITP will point to TREE_LIST of four elements, rather than a
- list of two elements, each itself a list of two elements. This
- routine transforms INIT from the former form into the latter. The
- revised initializer is returned. */
+ gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+
+ if (TYPE_DOMAIN (type))
+ max_index = array_type_nelts (type);
+
+ return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
+}
+
+/* Subroutine of reshape_init_r, processes the initializers for vectors.
+ Parameters are the same of reshape_init_r. */
+
+static tree
+reshape_init_vector (tree type, reshape_iter *d)
+{
+ tree max_index = NULL_TREE;
+ tree rtype;
+
+ gcc_assert (TREE_CODE (type) == VECTOR_TYPE);
+
+ if (COMPOUND_LITERAL_P (d->cur->value))
+ {
+ tree value = d->cur->value;
+ if (!same_type_p (TREE_TYPE (value), type))
+ {
+ error ("invalid type %qT as initializer for a vector of type %qT",
+ TREE_TYPE (d->cur->value), type);
+ value = error_mark_node;
+ }
+ ++d->cur;
+ return value;
+ }
+
+ /* For a vector, the representation type is a struct
+ containing a single member which is an array of the
+ appropriate size. */
+ rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+ if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
+ max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS (rtype)));
+
+ return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
+}
+
+/* Subroutine of reshape_init_r, processes the initializers for classes
+ or union. Parameters are the same of reshape_init_r. */
static tree
-reshape_init (tree type, tree *initp)
+reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
{
- tree inits;
- tree old_init;
- tree old_init_value;
+ tree field;
tree new_init;
- bool brace_enclosed_p;
- bool string_init_p;
- old_init = *initp;
- old_init_value = (TREE_CODE (*initp) == TREE_LIST
- ? TREE_VALUE (*initp) : old_init);
+ gcc_assert (CLASS_TYPE_P (type));
- my_friendly_assert (old_init_value, 20030723);
+ /* The initializer for a class is always a CONSTRUCTOR. */
+ new_init = build_constructor (NULL_TREE, NULL);
+ field = next_initializable_field (TYPE_FIELDS (type));
- /* If the initializer is brace-enclosed, pull initializers from the
- enclosed elements. Advance past the brace-enclosed initializer
- now. */
- if (TREE_CODE (old_init_value) == CONSTRUCTOR
- && TREE_TYPE (old_init_value) == NULL_TREE
- && TREE_HAS_CONSTRUCTOR (old_init_value))
+ if (!field)
{
- *initp = TREE_CHAIN (old_init);
- TREE_CHAIN (old_init) = NULL_TREE;
- inits = CONSTRUCTOR_ELTS (old_init_value);
- initp = &inits;
- brace_enclosed_p = true;
+ /* [dcl.init.aggr]
+
+ An initializer for an aggregate member that is an
+ empty class shall have the form of an empty
+ initializer-list {}. */
+ if (!first_initializer_p)
+ {
+ error ("initializer for %qT must be brace-enclosed", type);
+ return error_mark_node;
+ }
+ return new_init;
}
- else
+
+ /* Loop through the initializable fields, gathering initializers. */
+ while (d->cur != d->end)
{
- inits = NULL_TREE;
- brace_enclosed_p = false;
+ tree field_init;
+
+ /* Handle designated initializers, as an extension. */
+ if (d->cur->index)
+ {
+ field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);
+
+ if (!field || TREE_CODE (field) != FIELD_DECL)
+ {
+ error ("%qT has no non-static data member named %qD", type,
+ d->cur->index);
+ return error_mark_node;
+ }
+ }
+
+ /* If we processed all the member of the class, we are done. */
+ if (!field)
+ break;
+
+ field_init = reshape_init_r (TREE_TYPE (field), d,
+ /*first_initializer_p=*/false);
+ CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), field, field_init);
+
+ /* [dcl.init.aggr]
+
+ When a union is initialized with a brace-enclosed
+ initializer, the braces shall only contain an
+ initializer for the first member of the union. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
+
+ field = next_initializable_field (TREE_CHAIN (field));
}
+ return new_init;
+}
+
+/* Subroutine of reshape_init, which processes a single initializer (part of
+ a CONSTRUCTOR). TYPE is the type of the variable being initialized, D is the
+ iterator within the CONSTRUCTOR which points to the initializer to process.
+ FIRST_INITIALIZER_P is true if this is the first initializer of the
+ CONSTRUCTOR node. */
+
+static tree
+reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
+{
+ tree init = d->cur->value;
+
/* A non-aggregate type is always initialized with a single
initializer. */
if (!CP_AGGREGATE_TYPE_P (type))
- {
- *initp = TREE_CHAIN (old_init);
- TREE_CHAIN (old_init) = NULL_TREE;
- /* It is invalid to initialize a non-aggregate type with a
- brace-enclosed initializer. */
- if (brace_enclosed_p)
- {
- error ("brace-enclosed initializer used to initialize `%T'",
- type);
- if (TREE_CODE (old_init) == TREE_LIST)
- TREE_VALUE (old_init) = error_mark_node;
- else
- old_init = error_mark_node;
- }
-
- return old_init;
- }
+ {
+ /* It is invalid to initialize a non-aggregate type with a
+ brace-enclosed initializer.
+ We need to check for BRACE_ENCLOSED_INITIALIZER_P here because
+ of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is
+ a CONSTRUCTOR (with a record type). */
+ if (TREE_CODE (init) == CONSTRUCTOR
+ && BRACE_ENCLOSED_INITIALIZER_P (init)) /* p7626.C */
+ {
+ error ("braces around scalar initializer for type %qT", type);
+ init = error_mark_node;
+ }
+
+ d->cur++;
+ return init;
+ }
/* [dcl.init.aggr]
@@ -4328,127 +4609,130 @@ reshape_init (tree type, tree *initp)
non-empty subaggregate, brace elision is assumed and the
initializer is considered for the initialization of the first
member of the subaggregate. */
- if (!brace_enclosed_p
- && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))
+ if (TREE_CODE (init) != CONSTRUCTOR
+ && can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL))
{
- *initp = TREE_CHAIN (old_init);
- TREE_CHAIN (old_init) = NULL_TREE;
- return old_init;
+ d->cur++;
+ return init;
}
- string_init_p = false;
- if (TREE_CODE (old_init_value) == STRING_CST
- && TREE_CODE (type) == ARRAY_TYPE
- && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
- {
- /* [dcl.init.string]
+ /* [dcl.init.string]
- A char array (whether plain char, signed char, or unsigned char)
- can be initialized by a string-literal (optionally enclosed in
- braces); a wchar_t array can be initialized by a wide
- string-literal (optionally enclosed in braces). */
- new_init = old_init;
- /* Move past the initializer. */
- *initp = TREE_CHAIN (old_init);
- TREE_CHAIN (old_init) = NULL_TREE;
- string_init_p = true;
- }
- else
+ A char array (whether plain char, signed char, or unsigned char)
+ can be initialized by a string-literal (optionally enclosed in
+ braces); a wchar_t array can be initialized by a wide
+ string-literal (optionally enclosed in braces). */
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
{
- /* Build a CONSTRUCTOR to hold the contents of the aggregate. */
- new_init = build_constructor (type, NULL_TREE);
- TREE_HAS_CONSTRUCTOR (new_init) = 1;
+ tree str_init = init;
- if (CLASS_TYPE_P (type))
+ /* Strip one level of braces if and only if they enclose a single
+ element (as allowed by [dcl.init.string]). */
+ if (!first_initializer_p
+ && TREE_CODE (str_init) == CONSTRUCTOR
+ && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (str_init)) == 1)
{
- tree field;
+ str_init = VEC_index (constructor_elt,
+ CONSTRUCTOR_ELTS (str_init), 0)->value;
+ }
- field = next_initializable_field (TYPE_FIELDS (type));
+ /* If it's a string literal, then it's the initializer for the array
+ as a whole. Otherwise, continue with normal initialization for
+ array types (one value per array element). */
+ if (TREE_CODE (str_init) == STRING_CST)
+ {
+ d->cur++;
+ return str_init;
+ }
+ }
- if (!field)
- {
- /* [dcl.init.aggr]
-
- An initializer for an aggregate member that is an
- empty class shall have the form of an empty
- initializer-list {}. */
- if (!brace_enclosed_p)
- {
- error ("initializer for `%T' must be brace-enclosed",
- type);
- return error_mark_node;
- }
- }
+ /* The following cases are about aggregates. If we are not within a full
+ initializer already, and there is not a CONSTRUCTOR, it means that there
+ is a missing set of braces (that is, we are processing the case for
+ which reshape_init exists). */
+ if (!first_initializer_p)
+ {
+ if (TREE_CODE (init) == CONSTRUCTOR)
+ {
+ if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))
+ /* There is no need to reshape pointer-to-member function
+ initializers, as they are always constructed correctly
+ by the front end. */
+ ;
+ else if (COMPOUND_LITERAL_P (init))
+ /* For a nested compound literal, there is no need to reshape since
+ brace elision is not allowed. Even if we decided to allow it,
+ we should add a call to reshape_init in finish_compound_literal,
+ before calling digest_init, so changing this code would still
+ not be necessary. */
+ gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
else
{
- /* Loop through the initializable fields, gathering
- initializers. */
- while (*initp)
- {
- tree field_init;
-
- /* Handle designated initializers, as an extension. */
- if (TREE_PURPOSE (*initp))
- {
- if (pedantic)
- pedwarn ("ISO C++ does not allow designated initializers");
- field = lookup_field_1 (type, TREE_PURPOSE (*initp),
- /*want_type=*/false);
- if (!field || TREE_CODE (field) != FIELD_DECL)
- error ("`%T' has no non-static data member named `%D'",
- type, TREE_PURPOSE (*initp));
- }
- if (!field)
- break;
-
- field_init = reshape_init (TREE_TYPE (field), initp);
- if (field_init == error_mark_node)
- return error_mark_node;
- TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
- CONSTRUCTOR_ELTS (new_init) = field_init;
- /* [dcl.init.aggr]
-
- When a union is initialized with a brace-enclosed
- initializer, the braces shall only contain an
- initializer for the first member of the union. */
- if (TREE_CODE (type) == UNION_TYPE)
- break;
- field = next_initializable_field (TREE_CHAIN (field));
- }
+ ++d->cur;
+ gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
+ return reshape_init (type, init);
}
}
- else if ((TREE_CODE (type) == ARRAY_TYPE)|| (TREE_CODE (type) == VECTOR_TYPE))
- {
- tree max_index;
- /* If the bound of the array is known, take no more initializers
- than are allowed. */
- max_index = ((TYPE_DOMAIN (type) && (TREE_CODE (type) == ARRAY_TYPE))
- ? array_type_nelts (type) : NULL_TREE);
- if (!reshape_init_array (TREE_TYPE (type), max_index,
- initp, new_init))
- return error_mark_node;
- }
- else
- abort ();
+ warning (OPT_Wmissing_braces, "missing braces around initializer for %qT",
+ type);
+ }
- /* The initializers were placed in reverse order in the
- CONSTRUCTOR. */
- CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
+ /* Dispatch to specialized routines. */
+ if (CLASS_TYPE_P (type))
+ return reshape_init_class (type, d, first_initializer_p);
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ return reshape_init_array (type, d);
+ else if (TREE_CODE (type) == VECTOR_TYPE)
+ return reshape_init_vector (type, d);
+ else
+ gcc_unreachable();
+}
- if (TREE_CODE (old_init) == TREE_LIST)
- new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
- }
+/* Undo the brace-elision allowed by [dcl.init.aggr] in a
+ brace-enclosed aggregate initializer.
- /* If there are more initializers than necessary, issue a
- diagnostic. */
- if (*initp)
- {
- if (brace_enclosed_p)
- error ("too many initializers for `%T'", type);
- else if (warn_missing_braces && !string_init_p)
- warning ("missing braces around initializer");
- }
+ INIT is the CONSTRUCTOR containing the list of initializers describing
+ a brace-enclosed initializer for an entity of the indicated aggregate TYPE.
+ It may not presently match the shape of the TYPE; for example:
+
+ struct S { int a; int b; };
+ struct S a[] = { 1, 2, 3, 4 };
+
+ Here INIT will hold a VEC of four elements, rather than a
+ VEC of two elements, each itself a VEC of two elements. This
+ routine transforms INIT from the former form into the latter. The
+ revised CONSTRUCTOR node is returned. */
+
+tree
+reshape_init (tree type, tree init)
+{
+ VEC(constructor_elt, gc) *v;
+ reshape_iter d;
+ tree new_init;
+
+ gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
+
+ v = CONSTRUCTOR_ELTS (init);
+
+ /* An empty constructor does not need reshaping, and it is always a valid
+ initializer. */
+ if (VEC_empty (constructor_elt, v))
+ return init;
+
+ /* Recurse on this CONSTRUCTOR. */
+ d.cur = VEC_index (constructor_elt, v, 0);
+ d.end = d.cur + VEC_length (constructor_elt, v);
+
+ new_init = reshape_init_r (type, &d, true);
+ if (new_init == error_mark_node)
+ return error_mark_node;
+
+ /* Make sure all the element of the constructor were used. Otherwise,
+ issue an error about exceeding initializers. */
+ if (d.cur != d.end)
+ error ("too many initializers for %qT", type);
return new_init;
}
@@ -4466,68 +4750,74 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
tree type = TREE_TYPE (decl);
tree init_code = NULL;
- /* If `start_decl' didn't like having an initialization, ignore it now. */
- if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
- init = NULL_TREE;
-
- /* If an initializer is present, DECL_INITIAL has been
- error_mark_node, to indicate that an as-of-yet unevaluated
- initialization will occur. From now on, DECL_INITIAL reflects
- the static initialization -- if any -- of DECL. */
- DECL_INITIAL (decl) = NULL_TREE;
-
/* Things that are going to be initialized need to have complete
type. */
TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
if (type == error_mark_node)
/* We will have already complained. */
- init = NULL_TREE;
- else if (init && COMPLETE_TYPE_P (type)
- && !TREE_CONSTANT (TYPE_SIZE (type)))
+ return NULL_TREE;
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
{
- error ("variable-sized object `%D' may not be initialized", decl);
- init = NULL_TREE;
+ tree element_type = TREE_TYPE (type);
+
+ /* The array type itself need not be complete, because the
+ initializer may tell us how many elements are in the array.
+ But, the elements of the array must be complete. */
+ if (!COMPLETE_TYPE_P (complete_type (element_type)))
+ {
+ error ("elements of array %q#D have incomplete type", decl);
+ return NULL_TREE;
+ }
+ /* It is not valid to initialize an a VLA. */
+ if (init
+ && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
+ || !TREE_CONSTANT (TYPE_SIZE (element_type))))
+ {
+ error ("variable-sized object %qD may not be initialized", decl);
+ return NULL_TREE;
+ }
}
- else if (TREE_CODE (type) == ARRAY_TYPE
- && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
+ else if (!COMPLETE_TYPE_P (type))
{
- error ("elements of array `%#D' have incomplete type", decl);
- init = NULL_TREE;
+ error ("%qD has incomplete type", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ return NULL_TREE;
}
- else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+ else
+ /* There is no way to make a variable-sized class type in GNU C++. */
+ gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
+
+ if (!CP_AGGREGATE_TYPE_P (type)
+ && init && BRACE_ENCLOSED_INITIALIZER_P (init)
+ && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) != 1)
{
- error ("`%D' has incomplete type", decl);
+ error ("scalar object %qD requires one element in initializer", decl);
TREE_TYPE (decl) = error_mark_node;
- init = NULL_TREE;
+ return NULL_TREE;
}
if (TREE_CODE (decl) == CONST_DECL)
{
- my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);
+ gcc_assert (TREE_CODE (type) != REFERENCE_TYPE);
DECL_INITIAL (decl) = init;
- my_friendly_assert (init != NULL_TREE, 149);
+ gcc_assert (init != NULL_TREE);
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
init = grok_reference_init (decl, type, init, cleanup);
else if (init)
{
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+ /* Do not reshape constructors of vectors (they don't need to be
+ reshaped. */
+ if (TREE_CODE (init) == CONSTRUCTOR
+ && !COMPOUND_LITERAL_P (init)
+ && !TREE_TYPE (init)) /* ptrmemfunc */
{
- /* [dcl.init] paragraph 13,
- If T is a scalar type, then a declaration of the form
- T x = { a };
- is equivalent to
- T x = a;
-
- reshape_init will complain about the extra braces,
- and doesn't do anything useful in the case where TYPE is
- scalar, so just don't call it. */
- if (CP_AGGREGATE_TYPE_P (type))
- init = reshape_init (type, &init);
+ init = reshape_init (type, init);
if ((*targetm.vector_opaque_p) (type))
{
@@ -4540,19 +4830,19 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
array size from the initializer. */
maybe_deduce_size_from_array_init (decl, init);
type = TREE_TYPE (decl);
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
- TREE_TYPE (init) = type;
+ if (type == error_mark_node)
+ return NULL_TREE;
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
goto initialize_aggr;
- else if (TREE_CODE (init) == CONSTRUCTOR
- && TREE_HAS_CONSTRUCTOR (init))
+ else if (TREE_CODE (init) == CONSTRUCTOR)
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
- error ("`%D' must be initialized by constructor, not by `{...}'",
+ error ("%qD must be initialized by constructor, "
+ "not by %<{...}%>",
decl);
init = error_mark_node;
}
@@ -4583,6 +4873,12 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
if (TREE_CODE (init) != TREE_VEC)
{
init_code = store_init_value (decl, init);
+ if (pedantic && TREE_CODE (type) == ARRAY_TYPE
+ && DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+ && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl)))
+ warning (0, "array %qD initialized by parenthesized string literal %qE",
+ decl, DECL_INITIAL (decl));
init = NULL;
}
}
@@ -4596,10 +4892,9 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
tree core_type = strip_array_types (type);
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized const members", decl);
+ error ("structure %qD with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized reference members",
- decl);
+ error ("structure %qD with uninitialized reference members", decl);
check_for_uninitialized_const_var (decl);
}
@@ -4607,7 +4902,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
check_for_uninitialized_const_var (decl);
if (init && init != error_mark_node)
- init_code = build (INIT_EXPR, type, decl, init);
+ init_code = build2 (INIT_EXPR, type, decl, init);
return init_code;
}
@@ -4619,11 +4914,32 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
{
int toplev = toplevel_bindings_p ();
int defer_p;
+ const char *filename;
+
+ /* Set the DECL_ASSEMBLER_NAME for the object. */
+ if (asmspec)
+ {
+ /* The `register' keyword, when used together with an
+ asm-specification, indicates that the variable should be
+ placed in a particular register. */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+ {
+ set_user_assembler_name (decl, asmspec);
+ DECL_HARD_REGISTER (decl) = 1;
+ }
+ else
+ {
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+ set_builtin_user_assembler_name (decl, asmspec);
+ set_user_assembler_name (decl, asmspec);
+ }
+ }
/* Handle non-variables up front. */
if (TREE_CODE (decl) != VAR_DECL)
{
- rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+ rest_of_decl_compilation (decl, toplev, at_eof);
return;
}
@@ -4631,22 +4947,11 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
member. */
if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl))
{
- my_friendly_assert (TREE_STATIC (decl), 19990828);
+ gcc_assert (TREE_STATIC (decl));
/* An in-class declaration of a static data member should be
external; it is only a declaration, and not a definition. */
if (init == NULL_TREE)
- my_friendly_assert (DECL_EXTERNAL (decl), 20000723);
- }
-
- /* Set the DECL_ASSEMBLER_NAME for the variable. */
- if (asmspec)
- {
- change_decl_assembler_name (decl, get_identifier (asmspec));
- /* The `register' keyword, when used together with an
- asm-specification, indicates that the variable should be
- placed in a particular register. */
- if (DECL_REGISTER (decl))
- DECL_C_HARD_REGISTER (decl) = 1;
+ gcc_assert (DECL_EXTERNAL (decl));
}
/* We don't create any RTL for local variables. */
@@ -4654,43 +4959,40 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
return;
/* We defer emission of local statics until the corresponding
- DECL_STMT is expanded. */
+ DECL_EXPR is expanded. */
defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl);
/* We try to defer namespace-scope static constants so that they are
not emitted into the object file unnecessarily. */
+ filename = input_filename;
if (!DECL_VIRTUAL_P (decl)
&& TREE_READONLY (decl)
&& DECL_INITIAL (decl) != NULL_TREE
&& DECL_INITIAL (decl) != error_mark_node
+ && filename != NULL
&& ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
&& toplev
&& !TREE_PUBLIC (decl))
{
/* Fool with the linkage of static consts according to #pragma
interface. */
- if (!interface_unknown && !TREE_PUBLIC (decl))
+ struct c_fileinfo *finfo = get_fileinfo (filename);
+ if (!finfo->interface_unknown && !TREE_PUBLIC (decl))
{
TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = interface_only;
+ DECL_EXTERNAL (decl) = finfo->interface_only;
}
defer_p = 1;
}
/* Likewise for template instantiations. */
- else if (DECL_COMDAT (decl))
+ else if (DECL_LANG_SPECIFIC (decl)
+ && DECL_IMPLICIT_INSTANTIATION (decl))
defer_p = 1;
- /* If we're deferring the variable, we only need to make RTL if
- there's an ASMSPEC. Otherwise, we'll lazily create it later when
- we need it. (There's no way to lazily create RTL for things that
- have assembly specs because the information about the specifier
- isn't stored in the tree, yet) */
- if (defer_p && asmspec)
- make_decl_rtl (decl, asmspec);
/* If we're not deferring, go ahead and assemble the variable. */
- else if (!defer_p)
- rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+ if (!defer_p)
+ rest_of_decl_compilation (decl, toplev, at_eof);
}
/* Generate code to initialize DECL (a local variable). */
@@ -4701,10 +5003,9 @@ initialize_local_var (tree decl, tree init)
tree type = TREE_TYPE (decl);
tree cleanup;
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == RESULT_DECL,
- 20021010);
- my_friendly_assert (!TREE_STATIC (decl), 20021010);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == RESULT_DECL);
+ gcc_assert (!TREE_STATIC (decl));
if (DECL_SIZE (decl) == NULL_TREE)
{
@@ -4725,7 +5026,7 @@ initialize_local_var (tree decl, tree init)
{
int saved_stmts_are_full_exprs_p;
- my_friendly_assert (building_stmt_tree (), 20000906);
+ gcc_assert (building_stmt_tree ());
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (init);
@@ -4754,26 +5055,48 @@ initialize_local_var (tree decl, tree init)
finish_decl_cleanup (decl, cleanup);
}
+/* DECL is a VAR_DECL for a compiler-generated variable with static
+ storage duration (like a virtual table) whose initializer is a
+ compile-time constant. INIT must be either a TREE_LIST of values,
+ or a CONSTRUCTOR. Initialize the variable and provide it to the
+ back end. */
+
+void
+initialize_artificial_var (tree decl, tree init)
+{
+ gcc_assert (DECL_ARTIFICIAL (decl));
+ if (TREE_CODE (init) == TREE_LIST)
+ init = build_constructor_from_list (NULL_TREE, init);
+ gcc_assert (TREE_CODE (init) == CONSTRUCTOR);
+ DECL_INITIAL (decl) = init;
+ DECL_INITIALIZED_P (decl) = 1;
+ determine_visibility (decl);
+ layout_var_decl (decl);
+ maybe_commonize_var (decl);
+ make_rtl_for_nonlocal_decl (decl, init, /*asmspec=*/NULL);
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
it must be determined now, from the initial value, or it is an error.
- INIT holds the value of an initializer that should be allowed to escape
- the normal rules.
+ INIT is the initializer (if any) for DECL. If INIT_CONST_EXPR_P is
+ true, then INIT is an integral constant expression.
FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0
if the (init) syntax was used. */
void
-cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
+cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
+ tree asmspec_tree, int flags)
{
tree type;
- tree ttype = NULL_TREE;
tree cleanup;
const char *asmspec = NULL;
int was_readonly = 0;
bool var_definition_p = false;
+ int saved_processing_template_decl;
if (decl == error_mark_node)
return;
@@ -4784,66 +5107,73 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
return;
}
- my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619);
+ gcc_assert (TREE_CODE (decl) != RESULT_DECL);
+ /* Parameters are handled by store_parm_decls, not cp_finish_decl. */
+ gcc_assert (TREE_CODE (decl) != PARM_DECL);
+
+ type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return;
/* Assume no cleanup is required. */
cleanup = NULL_TREE;
+ saved_processing_template_decl = processing_template_decl;
/* If a name was specified, get the string. */
if (global_scope_p (current_binding_level))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
- if (asmspec_tree)
+ if (asmspec_tree && asmspec_tree != error_mark_node)
asmspec = TREE_STRING_POINTER (asmspec_tree);
- if (init && TREE_CODE (init) == NAMESPACE_DECL)
- {
- error ("cannot initialize `%D' to namespace `%D'",
- decl, init);
- init = NULL_TREE;
- }
-
if (current_class_type
&& CP_DECL_CONTEXT (decl) == current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
- if (TREE_CODE (decl) == VAR_DECL
- && DECL_CONTEXT (decl)
- && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
- && DECL_CONTEXT (decl) != current_namespace
- && init)
+ if (processing_template_decl)
{
- /* Leave the namespace of the object. */
- pop_decl_namespace ();
- }
+ bool type_dependent_p;
- type = TREE_TYPE (decl);
+ /* Add this declaration to the statement-tree. */
+ if (at_function_scope_p ())
+ add_decl_expr (decl);
- if (type == error_mark_node)
- goto finish_end0;
+ type_dependent_p = dependent_type_p (type);
- if (TYPE_HAS_MUTABLE_P (type))
- TREE_READONLY (decl) = 0;
+ if (init && init_const_expr_p)
+ {
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+ if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
+ TREE_CONSTANT (decl) = 1;
+ }
- if (processing_template_decl)
- {
- /* Add this declaration to the statement-tree. */
- if (at_function_scope_p ())
- add_decl_stmt (decl);
+ if (!init
+ || !DECL_CLASS_SCOPE_P (decl)
+ || !DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+ || type_dependent_p
+ || value_dependent_expression_p (init)
+ /* Check also if initializer is a value dependent
+ { integral_constant_expression }. */
+ || (TREE_CODE (init) == CONSTRUCTOR
+ && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) == 1
+ && value_dependent_expression_p
+ (VEC_index (constructor_elt,
+ CONSTRUCTOR_ELTS (init), 0)->value)))
+ {
+ if (init)
+ DECL_INITIAL (decl) = init;
+ if (TREE_CODE (decl) == VAR_DECL
+ && !DECL_PRETTY_FUNCTION_P (decl)
+ && !type_dependent_p)
+ maybe_deduce_size_from_array_init (decl, init);
+ goto finish_end;
+ }
- if (init && DECL_INITIAL (decl))
- DECL_INITIAL (decl) = init;
- if (TREE_CODE (decl) == VAR_DECL
- && !DECL_PRETTY_FUNCTION_P (decl)
- && !dependent_type_p (TREE_TYPE (decl)))
- maybe_deduce_size_from_array_init (decl, init);
- goto finish_end0;
+ init = fold_non_dependent_expr (init);
+ processing_template_decl = 0;
}
- /* Parameters are handled by store_parm_decls, not cp_finish_decl. */
- my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
-
/* Take care of TYPE_DECLs up front. */
if (TREE_CODE (decl) == TYPE_DECL)
{
@@ -4851,7 +5181,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
- warning ("shadowing previous type declaration of `%#D'", decl);
+ warning (0, "shadowing previous type declaration of %q#D", decl);
set_identifier_type_value (DECL_NAME (decl), decl);
}
@@ -4862,34 +5192,38 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
&& !COMPLETE_TYPE_P (TREE_TYPE (decl)))
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
- rest_of_decl_compilation (decl, NULL,
- DECL_CONTEXT (decl) == NULL_TREE, at_eof);
+ rest_of_decl_compilation (decl, DECL_CONTEXT (decl) == NULL_TREE,
+ at_eof);
goto finish_end;
}
- if (TREE_CODE (decl) != FUNCTION_DECL)
- ttype = target_type (type);
-
-
- /* Currently, GNU C++ puts constants in text space, making them
- impossible to initialize. In the future, one would hope for
- an operating system which understood the difference between
- initialization and the running of a program. */
- if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl))
+ /* A reference will be modified here, as it is initialized. */
+ if (! DECL_EXTERNAL (decl)
+ && TREE_READONLY (decl)
+ && TREE_CODE (type) == REFERENCE_TYPE)
{
was_readonly = 1;
- if (TYPE_NEEDS_CONSTRUCTING (type)
- || TREE_CODE (type) == REFERENCE_TYPE)
- TREE_READONLY (decl) = 0;
+ TREE_READONLY (decl) = 0;
}
if (TREE_CODE (decl) == VAR_DECL)
{
/* Only PODs can have thread-local storage. Other types may require
various kinds of non-trivial initialization. */
- if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
- error ("`%D' cannot be thread-local because it has non-POD type `%T'",
+ if (DECL_THREAD_LOCAL_P (decl) && !pod_type_p (TREE_TYPE (decl)))
+ error ("%qD cannot be thread-local because it has non-POD type %qT",
decl, TREE_TYPE (decl));
+ /* If this is a local variable that will need a mangled name,
+ register it now. We must do this before processing the
+ initializer for the variable, since the initialization might
+ require a guard variable, and since the mangled name of the
+ guard variable will depend on the mangled name of this
+ variable. */
+ if (!processing_template_decl
+ && DECL_FUNCTION_SCOPE_P (decl)
+ && TREE_STATIC (decl)
+ && !DECL_ARTIFICIAL (decl))
+ push_local_name (decl);
/* Convert the initializer to the type of DECL, if we have not
already initialized DECL. */
if (!DECL_INITIALIZED_P (decl)
@@ -4899,32 +5233,52 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
is *not* defined. */
&& (!DECL_EXTERNAL (decl) || init))
{
+ if (init)
+ {
+ DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
+ if (init_const_expr_p)
+ {
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+ if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
+ TREE_CONSTANT (decl) = 1;
+ }
+ }
init = check_initializer (decl, init, flags, &cleanup);
/* Thread-local storage cannot be dynamically initialized. */
- if (DECL_THREAD_LOCAL (decl) && init)
+ if (DECL_THREAD_LOCAL_P (decl) && init)
{
- error ("`%D' is thread-local and so cannot be dynamically "
+ error ("%qD is thread-local and so cannot be dynamically "
"initialized", decl);
init = NULL_TREE;
}
+
+ /* Check that the initializer for a static data member was a
+ constant. Although we check in the parser that the
+ initializer is an integral constant expression, we do not
+ simplify division-by-zero at the point at which it
+ occurs. Therefore, in:
+
+ struct S { static const int i = 7 / 0; };
+
+ we issue an error at this point. It would
+ probably be better to forbid division by zero in
+ integral constant expressions. */
if (DECL_EXTERNAL (decl) && init)
{
- /* The static data member cannot be initialized by a
- non-constant when being declared. */
- error ("`%D' cannot be initialized by a non-constant expression"
+ error ("%qD cannot be initialized by a non-constant expression"
" when being declared", decl);
DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
init = NULL_TREE;
}
-
+
/* Handle:
-
+
[dcl.init]
-
+
The memory occupied by any object of static storage
duration is zero-initialized at program startup before
any other initialization takes place.
-
+
We cannot create an appropriate initializer until after
the type of DECL is finalized. If DECL_INITIAL is set,
then the DECL is statically initialized, and any
@@ -4951,43 +5305,38 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
}
/* Add this declaration to the statement-tree. This needs to happen
- after the call to check_initializer so that the DECL_STMT for a
- reference temp is added before the DECL_STMT for the reference itself. */
+ after the call to check_initializer so that the DECL_EXPR for a
+ reference temp is added before the DECL_EXPR for the reference itself. */
if (at_function_scope_p ())
- add_decl_stmt (decl);
-
- if (TREE_CODE (decl) == VAR_DECL)
- layout_var_decl (decl);
+ add_decl_expr (decl);
- /* Output the assembler code and/or RTL code for variables and functions,
- unless the type is an undefined structure or union.
- If not, it will get done when the type is completed. */
- if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+ /* Let the middle end know about variables and functions -- but not
+ static data members in uninstantiated class templates. */
+ if (!saved_processing_template_decl
+ && (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL))
{
if (TREE_CODE (decl) == VAR_DECL)
- maybe_commonize_var (decl);
+ {
+ layout_var_decl (decl);
+ maybe_commonize_var (decl);
+ }
make_rtl_for_nonlocal_decl (decl, init, asmspec);
+ /* Check for abstractness of the type. Notice that there is no
+ need to strip array types here since the check for those types
+ is already done within create_array_type_for_decl. */
if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
- abstract_virtuals_error (decl,
- strip_array_types (TREE_TYPE (type)));
- else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
- {
- /* If it's either a pointer or an array type, strip through all
- of them but the last one. If the last is an array type, issue
- an error if the element type is abstract. */
- while (POINTER_TYPE_P (TREE_TYPE (type))
- || TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == ARRAY_TYPE)
- abstract_virtuals_error (decl, TREE_TYPE (type));
- }
+ abstract_virtuals_error (decl, TREE_TYPE (type));
else
abstract_virtuals_error (decl, type);
- if (TREE_CODE (decl) == FUNCTION_DECL
+ /* This needs to happen after the linkage is set. */
+ determine_visibility (decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_TYPE (decl) == error_mark_node)
/* No initialization required. */
;
@@ -5003,20 +5352,15 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
/* A variable definition. */
if (DECL_FUNCTION_SCOPE_P (decl))
{
- /* This is a local declaration. */
- maybe_inject_for_scope_var (decl);
/* Initialize the local variable. */
if (processing_template_decl)
- {
- if (init || DECL_INITIAL (decl) == error_mark_node)
- DECL_INITIAL (decl) = init;
- }
+ DECL_INITIAL (decl) = init;
else if (!TREE_STATIC (decl))
initialize_local_var (decl, init);
}
/* If a variable is defined, and then a subsequent
- definintion with external linkage is encountered, we will
+ definition with external linkage is encountered, we will
get here twice for the same variable. We want to avoid
calling expand_static_init more than once. For variables
that are not static data members, we can call
@@ -5024,43 +5368,24 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
initializer. It is not legal to redeclare a static data
member, so this issue does not arise in that case. */
if (var_definition_p && TREE_STATIC (decl))
- expand_static_init (decl, init);
+ expand_static_init (decl, init);
}
- finish_end0:
-
- /* Undo call to `pushclass' that was done in `start_decl'
- due to initialization of qualified member variable.
- I.e., Foo::x = 10; */
- {
- tree context = CP_DECL_CONTEXT (decl);
- if (context
- && TYPE_P (context)
- && (TREE_CODE (decl) == VAR_DECL
- /* We also have a pushclass done that we need to undo here
- if we're at top level and declare a method. */
- || TREE_CODE (decl) == FUNCTION_DECL)
- /* If size hasn't been set, we're still defining it,
- and therefore inside the class body; don't pop
- the binding level.. */
- && COMPLETE_TYPE_P (context)
- && context == current_class_type)
- pop_nested_class ();
- }
}
/* If a CLEANUP_STMT was created to destroy a temporary bound to a
reference, insert it in the statement-tree now. */
if (cleanup)
- add_stmt (cleanup);
+ push_cleanup (decl, cleanup, false);
finish_end:
+ processing_template_decl = saved_processing_template_decl;
if (was_readonly)
TREE_READONLY (decl) = 1;
/* If this was marked 'used', be sure it will be output. */
if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- mark_referenced (DECL_ASSEMBLER_NAME (decl));
+ mark_decl_referenced (decl);
}
/* This is here for a midend callback from c-common.c. */
@@ -5068,7 +5393,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
void
finish_decl (tree decl, tree init, tree asmspec_tree)
{
- cp_finish_decl (decl, init, asmspec_tree, 0);
+ cp_finish_decl (decl, init, /*init_const_expr_p=*/false, asmspec_tree, 0);
}
/* Returns a declaration for a VAR_DECL as if:
@@ -5078,7 +5403,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
had been seen. Used to create compiler-generated global
variables. */
-tree
+static tree
declare_global_var (tree name, tree type)
{
tree decl;
@@ -5088,8 +5413,12 @@ declare_global_var (tree name, tree type)
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
- pushdecl (decl);
- cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+ /* If the user has explicitly declared this variable (perhaps
+ because the code we are compiling is part of a low-level runtime
+ library), then it is possible that our declaration will be merged
+ with theirs by pushdecl. */
+ decl = pushdecl (decl);
+ finish_decl (decl, NULL_TREE, NULL_TREE);
pop_from_top_level ();
return decl;
@@ -5107,6 +5436,7 @@ get_atexit_node (void)
tree fn_type;
tree fn_ptr_type;
const char *name;
+ bool use_aeabi_atexit;
if (atexit_node)
return atexit_node;
@@ -5120,6 +5450,7 @@ get_atexit_node (void)
We build up the argument types and then then function type
itself. */
+ use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
/* First, build the pointer-to-function type for the first
argument. */
arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
@@ -5127,18 +5458,29 @@ get_atexit_node (void)
fn_ptr_type = build_pointer_type (fn_type);
/* Then, build the rest of the argument types. */
arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
- arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+ if (use_aeabi_atexit)
+ {
+ arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+ arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
+ }
+ else
+ {
+ arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
+ arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+ }
/* And the final __cxa_atexit type. */
fn_type = build_function_type (integer_type_node, arg_types);
fn_ptr_type = build_pointer_type (fn_type);
- name = "__cxa_atexit";
+ if (use_aeabi_atexit)
+ name = "__aeabi_atexit";
+ else
+ name = "__cxa_atexit";
}
else
{
/* The declaration for `atexit' is:
- int atexit (void (*)());
+ int atexit (void (*)());
We build up the argument types and then then function type
itself. */
@@ -5183,8 +5525,6 @@ static GTY(()) int start_cleanup_cnt;
static tree
start_cleanup_fn (void)
{
- int old_interface_only = interface_only;
- int old_interface_unknown = interface_unknown;
char name[32];
tree parmtypes;
tree fntype;
@@ -5195,9 +5535,6 @@ start_cleanup_fn (void)
/* No need to mangle this. */
push_lang_context (lang_name_c);
- interface_only = 0;
- interface_unknown = 1;
-
/* Build the parameter-types. */
parmtypes = void_list_node;
/* Functions passed to __cxa_atexit take an additional parameter.
@@ -5235,10 +5572,7 @@ start_cleanup_fn (void)
}
pushdecl (fndecl);
- start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED);
-
- interface_unknown = old_interface_unknown;
- interface_only = old_interface_only;
+ start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
pop_lang_context ();
@@ -5258,7 +5592,7 @@ end_cleanup_fn (void)
/* Generate code to handle the destruction of DECL, an object with
static storage duration. */
-void
+tree
register_dtor_fn (tree decl)
{
tree cleanup;
@@ -5267,7 +5601,7 @@ register_dtor_fn (tree decl)
tree fcall;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
- return;
+ return void_zero_node;
/* Call build_cleanup before we enter the anonymous function so that
any access checks will be done relative to the current scope,
@@ -5281,13 +5615,13 @@ register_dtor_fn (tree decl)
to the original function, rather than the anonymous one. That
will make the back-end think that nested functions are in use,
which causes confusion. */
-
+
push_deferring_access_checks (dk_no_check);
fcall = build_cleanup (decl);
pop_deferring_access_checks ();
/* Create the body of the anonymous function. */
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ compound_stmt = begin_compound_stmt (BCS_FN_BODY);
finish_expr_stmt (fcall);
finish_compound_stmt (compound_stmt);
end_cleanup_fn ();
@@ -5298,15 +5632,23 @@ register_dtor_fn (tree decl)
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
- args = tree_cons (NULL_TREE,
+ args = tree_cons (NULL_TREE,
build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
NULL_TREE);
- args = tree_cons (NULL_TREE, null_pointer_node, args);
- args = tree_cons (NULL_TREE, cleanup, args);
+ if (targetm.cxx.use_aeabi_atexit ())
+ {
+ args = tree_cons (NULL_TREE, cleanup, args);
+ args = tree_cons (NULL_TREE, null_pointer_node, args);
+ }
+ else
+ {
+ args = tree_cons (NULL_TREE, null_pointer_node, args);
+ args = tree_cons (NULL_TREE, cleanup, args);
+ }
}
else
args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
- finish_expr_stmt (build_function_call (get_atexit_node (), args));
+ return build_function_call (get_atexit_node (), args);
}
/* DECL is a VAR_DECL with static storage duration. INIT, if present,
@@ -5316,35 +5658,41 @@ register_dtor_fn (tree decl)
static void
expand_static_init (tree decl, tree init)
{
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
- my_friendly_assert (TREE_STATIC (decl), 20021010);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ gcc_assert (TREE_STATIC (decl));
/* Some variables require no initialization. */
- if (!init
+ if (!init
&& !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
- if (! toplevel_bindings_p ())
+ if (DECL_FUNCTION_SCOPE_P (decl))
{
/* Emit code to perform this initialization but once. */
- tree if_stmt;
- tree then_clause;
- tree assignment;
- tree guard;
- tree guard_init;
+ tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
+ tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
+ tree guard, guard_addr, guard_addr_list;
+ tree acquire_fn, release_fn, abort_fn;
+ tree flag, begin;
/* Emit code to perform this initialization but once. This code
looks like:
- static int guard = 0;
- if (!guard) {
- // Do initialization.
- guard = 1;
- // Register variable for destruction at end of program.
+ static <type> guard;
+ if (!guard.first_byte) {
+ if (__cxa_guard_acquire (&guard)) {
+ bool flag = false;
+ try {
+ // Do initialization.
+ flag = true; __cxa_guard_release (&guard);
+ // Register variable for destruction at end of program.
+ } catch {
+ if (!flag) __cxa_guard_abort (&guard);
+ }
}
- Note that the `temp' variable is only set to 1 *after* the
+ Note that the `flag' variable is only set to 1 *after* the
initialization is complete. This ensures that an exception,
thrown during the construction, will cause the variable to
reinitialized when we pass through this code again, as per:
@@ -5355,161 +5703,145 @@ expand_static_init (tree decl, tree init)
initialization is not complete, so it will be tried again
the next time control enters the declaration.
- In theory, this process should be thread-safe, too; multiple
- threads should not be able to initialize the variable more
- than once. We don't yet attempt to ensure thread-safety. */
+ This process should be thread-safe, too; multiple threads
+ should not be able to initialize the variable more than
+ once. */
/* Create the guard variable. */
guard = get_guard (decl);
- /* Begin the conditional initialization. */
- if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
- then_clause = begin_compound_stmt (/*has_no_scope=*/false);
-
- /* Do the initialization itself. */
- assignment = init ? init : NULL_TREE;
-
- /* Once the assignment is complete, set TEMP to 1. Since the
- construction of the static object is complete at this point,
- we want to make sure TEMP is set to 1 even if a temporary
- constructed during the initialization throws an exception
- when it is destroyed. So, we combine the initialization and
- the assignment to TEMP into a single expression, ensuring
- that when we call finish_expr_stmt the cleanups will not be
- run until after TEMP is set to 1. */
- guard_init = set_guard (guard);
- if (assignment)
- assignment = build_compound_expr (assignment, guard_init);
+ /* This optimization isn't safe on targets with relaxed memory
+ consistency. On such targets we force synchronization in
+ __cxa_guard_acquire. */
+ if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
+ {
+ /* Begin the conditional initialization. */
+ if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
+ then_clause = begin_compound_stmt (BCS_NO_SCOPE);
+ }
+
+ if (flag_threadsafe_statics)
+ {
+ guard_addr = build_address (guard);
+ guard_addr_list = build_tree_list (NULL_TREE, guard_addr);
+
+ acquire_fn = get_identifier ("__cxa_guard_acquire");
+ release_fn = get_identifier ("__cxa_guard_release");
+ abort_fn = get_identifier ("__cxa_guard_abort");
+ if (!get_global_value_if_present (acquire_fn, &acquire_fn))
+ {
+ tree argtypes = tree_cons (NULL_TREE, TREE_TYPE (guard_addr),
+ void_list_node);
+ tree vfntype = build_function_type (void_type_node, argtypes);
+ acquire_fn = push_library_fn
+ (acquire_fn, build_function_type (integer_type_node, argtypes));
+ release_fn = push_library_fn (release_fn, vfntype);
+ abort_fn = push_library_fn (abort_fn, vfntype);
+ }
+ else
+ {
+ release_fn = identifier_global_value (release_fn);
+ abort_fn = identifier_global_value (abort_fn);
+ }
+
+ inner_if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list),
+ inner_if_stmt);
+
+ inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
+ begin = get_target_expr (boolean_false_node);
+ flag = TARGET_EXPR_SLOT (begin);
+
+ TARGET_EXPR_CLEANUP (begin)
+ = build3 (COND_EXPR, void_type_node, flag,
+ void_zero_node,
+ build_call (abort_fn, guard_addr_list));
+ CLEANUP_EH_ONLY (begin) = 1;
+
+ /* Do the initialization itself. */
+ init = add_stmt_to_compound (begin, init);
+ init = add_stmt_to_compound
+ (init, build2 (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
+ init = add_stmt_to_compound
+ (init, build_call (release_fn, guard_addr_list));
+ }
else
- assignment = guard_init;
- finish_expr_stmt (assignment);
+ init = add_stmt_to_compound (init, set_guard (guard));
/* Use atexit to register a function for destroying this static
variable. */
- register_dtor_fn (decl);
+ init = add_stmt_to_compound (init, register_dtor_fn (decl));
- finish_compound_stmt (then_clause);
- finish_then_clause (if_stmt);
- finish_if_stmt ();
- }
- else
- static_aggregates = tree_cons (init, decl, static_aggregates);
-}
+ finish_expr_stmt (init);
-/* Finish the declaration of a catch-parameter. */
+ if (flag_threadsafe_statics)
+ {
+ finish_compound_stmt (inner_then_clause);
+ finish_then_clause (inner_if_stmt);
+ finish_if_stmt (inner_if_stmt);
+ }
-tree
-start_handler_parms (tree declspecs, tree declarator)
-{
- tree decl;
- if (declspecs)
- {
- decl = grokdeclarator (declarator, declspecs, CATCHPARM,
- 1, NULL);
- if (decl == NULL_TREE)
- error ("invalid catch parameter");
+ if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
+ {
+ finish_compound_stmt (then_clause);
+ finish_then_clause (if_stmt);
+ finish_if_stmt (if_stmt);
+ }
}
else
- decl = NULL_TREE;
-
- return decl;
+ static_aggregates = tree_cons (init, decl, static_aggregates);
}
/* Make TYPE a complete type based on INITIAL_VALUE.
Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
- 2 if there was no information (in which case assume 0 if DO_DEFAULT). */
+ 2 if there was no information (in which case assume 0 if DO_DEFAULT),
+ 3 if the initializer list is empty (in pedantic mode). */
int
-complete_array_type (tree type, tree initial_value, int do_default)
+cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
{
- tree maxindex = NULL_TREE;
- int value = 0;
+ int failure;
+ tree type, elt_type;
if (initial_value)
{
/* An array of character type can be initialized from a
- brace-enclosed string constant. */
- if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))
- && TREE_CODE (initial_value) == CONSTRUCTOR
- && CONSTRUCTOR_ELTS (initial_value)
- && (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)))
- == STRING_CST)
- && TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE)
- initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (initial_value));
-
- /* Note MAXINDEX is really the maximum index, one less than the
- size. */
- if (TREE_CODE (initial_value) == STRING_CST)
- {
- int eltsize
- = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
- maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
- / eltsize) - 1, 0);
- }
- else if (TREE_CODE (initial_value) == CONSTRUCTOR)
- {
- tree elts = CONSTRUCTOR_ELTS (initial_value);
+ brace-enclosed string constant.
- maxindex = ssize_int (-1);
- for (; elts; elts = TREE_CHAIN (elts))
- {
- if (TREE_PURPOSE (elts))
- maxindex = TREE_PURPOSE (elts);
- else
- maxindex = size_binop (PLUS_EXPR, maxindex, ssize_int (1));
- }
- maxindex = copy_node (maxindex);
- }
- else
+ FIXME: this code is duplicated from reshape_init. Probably
+ we should just call reshape_init here? */
+ if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
+ && TREE_CODE (initial_value) == CONSTRUCTOR
+ && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (initial_value)))
{
- /* Make an error message unless that happened already. */
- if (initial_value != error_mark_node)
- value = 1;
- else
- initial_value = NULL_TREE;
+ VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
+ tree value = VEC_index (constructor_elt, v, 0)->value;
- /* Prevent further error messages. */
- maxindex = build_int_2 (0, 0);
+ if (TREE_CODE (value) == STRING_CST
+ && VEC_length (constructor_elt, v) == 1)
+ initial_value = value;
}
}
- if (!maxindex)
- {
- if (do_default)
- maxindex = build_int_2 (0, 0);
- value = 2;
- }
+ failure = complete_array_type (ptype, initial_value, do_default);
- if (maxindex)
+ /* We can create the array before the element type is complete, which
+ means that we didn't have these two bits set in the original type
+ either. In completing the type, we are expected to propagate these
+ bits. See also complete_type which does the same thing for arrays
+ of fixed size. */
+ type = *ptype;
+ if (TYPE_DOMAIN (type))
{
- tree itype;
- tree domain;
-
- domain = build_index_type (maxindex);
- TYPE_DOMAIN (type) = domain;
-
- if (! TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = domain;
- if (initial_value)
- itype = TREE_TYPE (initial_value);
- else
- itype = NULL;
- if (itype && !TYPE_DOMAIN (itype))
- TYPE_DOMAIN (itype) = domain;
- /* The type of the main variant should never be used for arrays
- of different sizes. It should only ever be completed with the
- size of the array. */
- if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)))
- TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
+ elt_type = TREE_TYPE (type);
+ TYPE_NEEDS_CONSTRUCTING (type) = TYPE_NEEDS_CONSTRUCTING (elt_type);
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (elt_type);
}
- /* Lay out the type now that we can get the real answer. */
-
- layout_type (type);
-
- return value;
+ return failure;
}
/* Return zero if something is declared to be a member of type
@@ -5522,11 +5854,9 @@ member_function_or_else (tree ctype, tree cur_type, enum overload_flags flags)
if (ctype && ctype != cur_type)
{
if (flags == DTOR_FLAG)
- error ("destructor for alien class `%T' cannot be a member",
- ctype);
+ error ("destructor for alien class %qT cannot be a member", ctype);
else
- error ("constructor for alien class `%T' cannot be a member",
- ctype);
+ error ("constructor for alien class %qT cannot be a member", ctype);
return 0;
}
return 1;
@@ -5539,28 +5869,86 @@ member_function_or_else (tree ctype, tree cur_type, enum overload_flags flags)
static void
bad_specifiers (tree object,
- const char* type,
- int virtualp,
- int quals,
- int inlinep,
- int friendp,
- int raises)
+ const char* type,
+ int virtualp,
+ int quals,
+ int inlinep,
+ int friendp,
+ int raises)
{
if (virtualp)
- error ("`%D' declared as a `virtual' %s", object, type);
+ error ("%qD declared as a %<virtual%> %s", object, type);
if (inlinep)
- error ("`%D' declared as an `inline' %s", object, type);
+ error ("%qD declared as an %<inline%> %s", object, type);
if (quals)
- error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
- object, type);
+ error ("%<const%> and %<volatile%> function specifiers on "
+ "%qD invalid in %s declaration",
+ object, type);
if (friendp)
- cp_error_at ("`%D' declared as a friend", object);
+ error ("%q+D declared as a friend", object);
if (raises
&& (TREE_CODE (object) == TYPE_DECL
|| (!TYPE_PTRFN_P (TREE_TYPE (object))
&& !TYPE_REFFN_P (TREE_TYPE (object))
&& !TYPE_PTRMEMFUNC_P (TREE_TYPE (object)))))
- cp_error_at ("`%D' declared with an exception specification", object);
+ error ("%q+D declared with an exception specification", object);
+}
+
+/* DECL is a member function or static data member and is presently
+ being defined. Check that the definition is taking place in a
+ valid namespace. */
+
+static void
+check_class_member_definition_namespace (tree decl)
+{
+ /* These checks only apply to member functions and static data
+ members. */
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL);
+ /* We check for problems with specializations in pt.c in
+ check_specialization_namespace, where we can issue better
+ diagnostics. */
+ if (processing_specialization)
+ return;
+ /* There are no restrictions on the placement of
+ explicit instantiations. */
+ if (processing_explicit_instantiation)
+ return;
+ /* [class.mfct]
+
+ A member function definition that appears outside of the
+ class definition shall appear in a namespace scope enclosing
+ the class definition.
+
+ [class.static.data]
+
+ The definition for a static data member shall appear in a
+ namespace scope enclosing the member's class definition. */
+ if (!is_ancestor (current_namespace, DECL_CONTEXT (decl)))
+ pedwarn ("definition of %qD is not in namespace enclosing %qT",
+ decl, DECL_CONTEXT (decl));
+}
+
+/* Build a PARM_DECL for the "this" parameter. TYPE is the
+ METHOD_TYPE for a non-static member function; QUALS are the
+ cv-qualifiers that apply to the function. */
+
+tree
+build_this_parm (tree type, cp_cv_quals quals)
+{
+ tree this_type;
+ tree qual_type;
+ tree parm;
+ cp_cv_quals this_quals;
+
+ this_type = TREE_VALUE (TYPE_ARG_TYPES (type));
+ /* The `this' parameter is implicitly `const'; it cannot be
+ assigned to. */
+ this_quals = (quals & TYPE_QUAL_RESTRICT) | TYPE_QUAL_CONST;
+ qual_type = cp_build_qualified_type (this_type, this_quals);
+ parm = build_artificial_parm (this_identifier, qual_type);
+ cp_apply_type_quals_to_decl (this_quals, parm);
+ return parm;
}
/* CTYPE is class type, or null if non-class.
@@ -5576,41 +5964,112 @@ bad_specifiers (tree object,
CHECK is 1 if we must find this method in CTYPE, 0 if we should
not look, and -1 if we should not call `grokclassfn' at all.
+ SFK is the kind of special function (if any) for the new function.
+
Returns `NULL_TREE' if something goes wrong, after issuing
applicable error messages. */
static tree
-grokfndecl (tree ctype,
- tree type,
- tree declarator,
+grokfndecl (tree ctype,
+ tree type,
+ tree declarator,
tree parms,
- tree orig_declarator,
- int virtualp,
- enum overload_flags flags,
- tree quals,
- tree raises,
- int check,
- int friendp,
- int publicp,
- int inlinep,
- int funcdef_flag,
- int template_count,
- tree in_namespace)
+ tree orig_declarator,
+ int virtualp,
+ enum overload_flags flags,
+ cp_cv_quals quals,
+ tree raises,
+ int check,
+ int friendp,
+ int publicp,
+ int inlinep,
+ special_function_kind sfk,
+ bool funcdef_flag,
+ int template_count,
+ tree in_namespace,
+ tree* attrlist)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
- int has_default_arg = 0;
tree t;
if (raises)
type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+ if (TREE_CODE (type) == METHOD_TYPE)
+ {
+ tree parm;
+ parm = build_this_parm (type, quals);
+ TREE_CHAIN (parm) = parms;
+ parms = parm;
+ }
DECL_ARGUMENTS (decl) = parms;
/* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
+ if (friendp
+ && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
+ {
+ if (funcdef_flag)
+ error
+ ("defining explicit specialization %qD in friend declaration",
+ orig_declarator);
+ else
+ {
+ tree fns = TREE_OPERAND (orig_declarator, 0);
+ tree args = TREE_OPERAND (orig_declarator, 1);
+
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ {
+ /* Something like `template <class T> friend void f<T>()'. */
+ error ("invalid use of template-id %qD in declaration "
+ "of primary template",
+ orig_declarator);
+ return NULL_TREE;
+ }
+
+
+ /* A friend declaration of the form friend void f<>(). Record
+ the information in the TEMPLATE_ID_EXPR. */
+ SET_DECL_IMPLICIT_INSTANTIATION (decl);
+
+ if (TREE_CODE (fns) == COMPONENT_REF)
+ {
+ /* Due to bison parser ickiness, we will have already looked
+ up an operator_name or PFUNCNAME within the current class
+ (see template_id in parse.y). If the current class contains
+ such a name, we'll get a COMPONENT_REF here. Undo that. */
+
+ gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
+ == current_class_type);
+ fns = TREE_OPERAND (fns, 1);
+ }
+ gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
+ || TREE_CODE (fns) == OVERLOAD);
+ DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
+
+ for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
+ if (TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
+ {
+ error ("default arguments are not allowed in declaration "
+ "of friend template specialization %qD",
+ decl);
+ return NULL_TREE;
+ }
+
+ if (inlinep)
+ {
+ error ("%<inline%> is not allowed in declaration of friend "
+ "template specialization %qD",
+ decl);
+ return NULL_TREE;
+ }
+ }
+ }
+
/* If this decl has namespace scope, set that up. */
if (in_namespace)
set_decl_namespace (decl, in_namespace, friendp);
@@ -5637,26 +6096,26 @@ grokfndecl (tree ctype,
}
if (ctype)
- DECL_CONTEXT (decl) = ctype;
+ {
+ DECL_CONTEXT (decl) = ctype;
+ if (funcdef_flag)
+ check_class_member_definition_namespace (decl);
+ }
if (ctype == NULL_TREE && DECL_MAIN_P (decl))
{
if (processing_template_decl)
- error ("cannot declare `::main' to be a template");
+ error ("cannot declare %<::main%> to be a template");
if (inlinep)
- error ("cannot declare `::main' to be inline");
+ error ("cannot declare %<::main%> to be inline");
if (!publicp)
- error ("cannot declare `::main' to be static");
- if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
- integer_type_node))
- error ("`main' must return `int'");
+ error ("cannot declare %<::main%> to be static");
inlinep = 0;
publicp = 1;
}
/* Members of anonymous types and local classes have no linkage; make
- them internal. */
- /* FIXME what if it gets a name from typedef? */
+ them internal. If a typedef is made later, this will be changed. */
if (ctype && (TYPE_ANONYMOUS_P (ctype)
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
@@ -5668,7 +6127,8 @@ grokfndecl (tree ctype,
declare an entity with linkage.
Only check this for public decls for now. See core 319, 389. */
- t = no_linkage_check (TREE_TYPE (decl));
+ t = no_linkage_check (TREE_TYPE (decl),
+ /*relaxed_p=*/false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
@@ -5677,17 +6137,16 @@ grokfndecl (tree ctype,
/* Allow this; it's pretty common in C. */;
else
{
- pedwarn ("non-local function `%#D' uses anonymous type",
+ pedwarn ("non-local function %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
- cp_pedwarn_at ("\
-`%#D' does not refer to the unqualified type, so it is not used for linkage",
- TYPE_NAME (t));
+ pedwarn ("%q+#D does not refer to the unqualified "
+ "type, so it is not used for linkage",
+ TYPE_NAME (t));
}
}
else
- pedwarn ("non-local function `%#D' uses local type `%T'",
- decl, t);
+ pedwarn ("non-local function %q#D uses local type %qT", decl, t);
}
}
@@ -5708,83 +6167,20 @@ grokfndecl (tree ctype,
DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
- if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
+ if (quals && TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("%smember function `%D' cannot have `%T' method qualifier",
- (ctype ? "static " : "non-"), decl, TREE_VALUE (quals));
- quals = NULL_TREE;
+ error ("%smember function %qD cannot have cv-qualifier",
+ (ctype ? "static " : "non-"), decl);
+ quals = TYPE_UNQUALIFIED;
}
- if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
- grok_op_properties (decl, /*complain=*/true);
+ if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))
+ && !grok_op_properties (decl, /*complain=*/true))
+ return NULL_TREE;
if (ctype && decl_function_context (decl))
DECL_NO_STATIC_CHAIN (decl) = 1;
- for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
- if (TREE_PURPOSE (t)
- && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
- {
- has_default_arg = 1;
- break;
- }
-
- if (friendp
- && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
- {
- if (funcdef_flag)
- error
- ("defining explicit specialization `%D' in friend declaration",
- orig_declarator);
- else
- {
- tree fns = TREE_OPERAND (orig_declarator, 0);
- tree args = TREE_OPERAND (orig_declarator, 1);
-
- if (PROCESSING_REAL_TEMPLATE_DECL_P ())
- {
- /* Something like `template <class T> friend void f<T>()'. */
- error ("invalid use of template-id `%D' in declaration of primary template",
- orig_declarator);
- return NULL_TREE;
- }
-
-
- /* A friend declaration of the form friend void f<>(). Record
- the information in the TEMPLATE_ID_EXPR. */
- SET_DECL_IMPLICIT_INSTANTIATION (decl);
-
- if (TREE_CODE (fns) == COMPONENT_REF)
- {
- /* Due to bison parser ickiness, we will have already looked
- up an operator_name or PFUNCNAME within the current class
- (see template_id in parse.y). If the current class contains
- such a name, we'll get a COMPONENT_REF here. Undo that. */
-
- my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
- == current_class_type, 20001120);
- fns = TREE_OPERAND (fns, 1);
- }
- my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE
- || TREE_CODE (fns) == OVERLOAD, 20001120);
- DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
-
- if (has_default_arg)
- {
- error ("default arguments are not allowed in declaration of friend template specialization `%D'",
- decl);
- return NULL_TREE;
- }
-
- if (inlinep)
- {
- error ("`inline' is not allowed in declaration of friend template specialization `%D'",
- decl);
- return NULL_TREE;
- }
- }
- }
-
if (funcdef_flag)
/* Make the init_value nonzero so pushdecl knows this is not
tentative. error_mark_node is replaced later with the BLOCK. */
@@ -5797,22 +6193,39 @@ grokfndecl (tree ctype,
if (check < 0)
return decl;
- if (flags == NO_SPECIAL && ctype && constructor_name_p (declarator, ctype))
- DECL_CONSTRUCTOR_P (decl) = 1;
-
- /* Function gets the ugly name, field gets the nice one. This call
- may change the type of the function (because of default
- parameters)! */
if (ctype != NULL_TREE)
- grokclassfn (ctype, decl, flags, quals);
+ {
+ if (sfk == sfk_constructor)
+ DECL_CONSTRUCTOR_P (decl) = 1;
+
+ grokclassfn (ctype, decl, flags);
+ }
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
- 2 * (funcdef_flag != 0) +
+ 2 * funcdef_flag +
4 * (friendp != 0));
if (decl == error_mark_node)
return NULL_TREE;
+ if (attrlist)
+ {
+ cplus_decl_attributes (&decl, *attrlist, 0);
+ *attrlist = NULL_TREE;
+ }
+
+ /* Check main's type after attributes have been applied. */
+ if (ctype == NULL_TREE && DECL_MAIN_P (decl)
+ && !same_type_p (TREE_TYPE (TREE_TYPE (decl)),
+ integer_type_node))
+ {
+ tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ tree newtype;
+ error ("%<::main%> must return %<int%>");
+ newtype = build_function_type (integer_type_node, oldtypeargs);
+ TREE_TYPE (decl) = newtype;
+ }
+
if (ctype != NULL_TREE
&& (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
@@ -5820,28 +6233,29 @@ grokfndecl (tree ctype,
tree old_decl;
old_decl = check_classfn (ctype, decl,
- processing_template_decl
- > template_class_depth (ctype));
-
- if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
- /* Because grokfndecl is always supposed to return a
- FUNCTION_DECL, we pull out the DECL_TEMPLATE_RESULT
- here. We depend on our callers to figure out that its
- really a template that's being returned. */
- old_decl = DECL_TEMPLATE_RESULT (old_decl);
-
- if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
- && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- /* Remove the `this' parm added by grokclassfn.
- XXX Isn't this done in start_function, too? */
- revert_static_member_fn (decl);
- if (old_decl && DECL_ARTIFICIAL (old_decl))
- error ("definition of implicitly-declared `%D'", old_decl);
-
+ (processing_template_decl
+ > template_class_depth (ctype))
+ ? current_template_parms
+ : NULL_TREE);
if (old_decl)
{
tree ok;
- bool pop_p;
+ tree pushed_scope;
+
+ if (TREE_CODE (old_decl) == TEMPLATE_DECL)
+ /* Because grokfndecl is always supposed to return a
+ FUNCTION_DECL, we pull out the DECL_TEMPLATE_RESULT
+ here. We depend on our callers to figure out that its
+ really a template that's being returned. */
+ old_decl = DECL_TEMPLATE_RESULT (old_decl);
+
+ if (DECL_STATIC_FUNCTION_P (old_decl)
+ && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
+ /* Remove the `this' parm added by grokclassfn.
+ XXX Isn't this done in start_function, too? */
+ revert_static_member_fn (decl);
+ if (DECL_ARTIFICIAL (old_decl))
+ error ("definition of implicitly-declared %qD", old_decl);
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
@@ -5850,13 +6264,13 @@ grokfndecl (tree ctype,
/* Attempt to merge the declarations. This can fail, in
the case of some invalid specialization declarations. */
- pop_p = push_scope (ctype);
- ok = duplicate_decls (decl, old_decl);
- if (pop_p)
- pop_scope (ctype);
+ pushed_scope = push_scope (ctype);
+ ok = duplicate_decls (decl, old_decl, friendp);
+ if (pushed_scope)
+ pop_scope (pushed_scope);
if (!ok)
{
- error ("no `%#D' member function declared in class `%T'",
+ error ("no %q#D member function declared in class %qT",
decl, ctype);
return NULL_TREE;
}
@@ -5876,7 +6290,26 @@ grokfndecl (tree ctype,
return decl;
}
-/* Create a VAR_DECL named NAME with the indicated TYPE.
+/* DECL is a VAR_DECL for a static data member. Set flags to reflect
+ the linkage that DECL will receive in the object file. */
+
+static void
+set_linkage_for_static_data_member (tree decl)
+{
+ /* A static data member always has static storage duration and
+ external linkage. Note that static data members are forbidden in
+ local classes -- the only situation in which a class has
+ non-external linkage. */
+ TREE_PUBLIC (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ /* For non-template classes, static data members are always put
+ out in exactly those files where they are defined, just as
+ with ordinary namespace-scope variables. */
+ if (!processing_template_decl)
+ DECL_INTERFACE_KNOWN (decl) = 1;
+}
+
+/* Create a VAR_DECL named NAME with the indicated TYPE.
If SCOPE is non-NULL, it is the class type or namespace containing
the variable. If SCOPE is NULL, the variable should is created in
@@ -5884,36 +6317,28 @@ grokfndecl (tree ctype,
static tree
grokvardecl (tree type,
- tree name,
- RID_BIT_TYPE * specbits_in,
- int initialized,
- int constp,
- tree scope)
+ tree name,
+ const cp_decl_specifier_seq *declspecs,
+ int initialized,
+ int constp,
+ tree scope)
{
tree decl;
tree explicit_scope;
- RID_BIT_TYPE specbits;
- my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
- 20020808);
-
- specbits = *specbits_in;
+ gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE);
/* Compute the scope in which to place the variable, but remember
- whether or not that scope was explicitly specified by the user. */
+ whether or not that scope was explicitly specified by the user. */
explicit_scope = scope;
if (!scope)
{
/* An explicit "extern" specifier indicates a namespace-scope
variable. */
- if (RIDBIT_SETP (RID_EXTERN, specbits))
+ if (declspecs->storage_class == sc_extern)
scope = current_namespace;
else if (!at_function_scope_p ())
- {
- scope = current_scope ();
- if (!scope)
- scope = current_namespace;
- }
+ scope = current_scope ();
}
if (scope
@@ -5922,7 +6347,7 @@ grokvardecl (tree type,
(TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
/* Similarly for namespace-scope variables with language linkage
other than C++. */
- || (TREE_CODE (scope) == NAMESPACE_DECL
+ || (TREE_CODE (scope) == NAMESPACE_DECL
&& current_lang_name != lang_name_cplusplus)
/* Similarly for static data members. */
|| TYPE_P (scope)))
@@ -5933,47 +6358,40 @@ grokvardecl (tree type,
if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
set_decl_namespace (decl, explicit_scope, 0);
else
- DECL_CONTEXT (decl) = scope;
-
- if (name && scope && current_lang_name != lang_name_c)
- /* We can't mangle lazily here because we don't have any
- way to recover whether or not a variable was `extern
- "C"' later. */
- mangle_decl (decl);
+ DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
- if (RIDBIT_SETP (RID_EXTERN, specbits))
+ if (declspecs->storage_class == sc_extern)
{
DECL_THIS_EXTERN (decl) = 1;
DECL_EXTERNAL (decl) = !initialized;
}
- /* In class context, static means one per class,
- public access, and static storage. */
if (DECL_CLASS_SCOPE_P (decl))
{
- TREE_PUBLIC (decl) = 1;
- TREE_STATIC (decl) = 1;
+ set_linkage_for_static_data_member (decl);
+ /* This function is only called with out-of-class definitions. */
DECL_EXTERNAL (decl) = 0;
+ check_class_member_definition_namespace (decl);
}
/* At top level, either `static' or no s.c. makes a definition
(perhaps tentative), and absence of `static' makes it public. */
else if (toplevel_bindings_p ())
{
- TREE_PUBLIC (decl) = (RIDBIT_NOTSETP (RID_STATIC, specbits)
+ TREE_PUBLIC (decl) = (declspecs->storage_class != sc_static
&& (DECL_THIS_EXTERN (decl) || ! constp));
TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
}
/* Not at top level, only `static' makes a static definition. */
else
{
- TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits);
+ TREE_STATIC (decl) = declspecs->storage_class == sc_static;
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
- if (RIDBIT_SETP (RID_THREAD, specbits))
+ if (declspecs->specs[(int)ds_thread])
{
if (targetm.have_tls)
- DECL_THREAD_LOCAL (decl) = 1;
+ DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
else
/* A mere warning is sure to result in improper semantics
at runtime. Don't bother to allow this to compile. */
@@ -5987,16 +6405,34 @@ grokvardecl (tree type,
declare an entity with linkage.
Only check this for public decls for now. */
- tree t = no_linkage_check (TREE_TYPE (decl));
+ tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
- /* Ignore for now; `enum { foo } e' is pretty common. */;
+ {
+ if (DECL_EXTERN_C_P (decl))
+ /* Allow this; it's pretty common in C. */
+ ;
+ else
+ {
+ /* DRs 132, 319 and 389 seem to indicate types with
+ no linkage can only be used to declare extern "C"
+ entities. Since it's not always an error in the
+ ISO C++ 90 Standard, we only issue a warning. */
+ warning (0, "non-local variable %q#D uses anonymous type",
+ decl);
+ if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
+ warning (0, "%q+#D does not refer to the unqualified "
+ "type, so it is not used for linkage",
+ TYPE_NAME (t));
+ }
+ }
else
- pedwarn ("non-local variable `%#D' uses local type `%T'",
- decl, t);
+ warning (0, "non-local variable %q#D uses local type %qT", decl, t);
}
}
+ else
+ DECL_INTERFACE_KNOWN (decl) = 1;
return decl;
}
@@ -6028,6 +6464,8 @@ build_ptrmemfunc_type (tree type)
= build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
t = make_aggr_type (RECORD_TYPE);
+ xref_basetypes (t, NULL_TREE);
+
/* Let the front-end know this is a pointer to member function... */
TYPE_PTRMEMFUNC_FLAG (t) = 1;
/* ... and not really an aggregate. */
@@ -6035,11 +6473,11 @@ build_ptrmemfunc_type (tree type)
field = build_decl (FIELD_DECL, pfn_identifier, type);
fields = field;
-
+
field = build_decl (FIELD_DECL, delta_identifier, delta_type_node);
TREE_CHAIN (field) = fields;
fields = field;
-
+
finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
/* Zap out the name so that the back-end will give us the debugging
@@ -6075,19 +6513,18 @@ build_ptrmem_type (tree class_type, tree member_type)
tree arg_types;
arg_types = TYPE_ARG_TYPES (member_type);
- class_type = (cp_build_qualified_type
+ class_type = (cp_build_qualified_type
(class_type,
cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)))));
- member_type
- = build_method_type_directly (class_type,
+ member_type
+ = build_method_type_directly (class_type,
TREE_TYPE (member_type),
TREE_CHAIN (arg_types));
return build_ptrmemfunc_type (build_pointer_type (member_type));
}
else
{
- my_friendly_assert (TREE_CODE (member_type) != FUNCTION_TYPE,
- 20030716);
+ gcc_assert (TREE_CODE (member_type) != FUNCTION_TYPE);
return build_offset_type (class_type, member_type);
}
}
@@ -6108,19 +6545,22 @@ check_static_variable_definition (tree decl, tree type)
required. */
if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
{
- error ("invalid in-class initialization of static data member of non-integral type `%T'",
+ error ("invalid in-class initialization of static data member "
+ "of non-integral type %qT",
type);
/* If we just return the declaration, crashes will sometimes
- occur. We therefore return void_type_node, as if this was a
+ occur. We therefore return void_type_node, as if this were a
friend declaration, to cause callers to completely ignore
this declaration. */
return 1;
}
else if (!CP_TYPE_CONST_P (type))
- error ("ISO C++ forbids in-class initialization of non-const static member `%D'",
- decl);
+ error ("ISO C++ forbids in-class initialization of non-const "
+ "static member %qD",
+ decl);
else if (pedantic && !INTEGRAL_TYPE_P (type))
- pedwarn ("ISO C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+ pedwarn ("ISO C++ forbids initialization of member constant "
+ "%qD of non-integral type %qT", decl, type);
return 0;
}
@@ -6132,16 +6572,20 @@ check_static_variable_definition (tree decl, tree type)
tree
compute_array_index_type (tree name, tree size)
{
- tree type = TREE_TYPE (size);
+ tree type;
tree itype;
+ if (error_operand_p (size))
+ return error_mark_node;
+
+ type = TREE_TYPE (size);
/* The array bound must be an integer type. */
if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
{
if (name)
- error ("size of array `%D' has non-integral type `%T'", name, type);
+ error ("size of array %qD has non-integral type %qT", name, type);
else
- error ("size of array has non-integral type `%T'", type);
+ error ("size of array has non-integral type %qT", type);
size = integer_one_node;
type = TREE_TYPE (size);
}
@@ -6159,7 +6603,7 @@ compute_array_index_type (tree name, tree size)
STRIP_TYPE_NOPS (size);
/* It might be a const variable or enumeration constant. */
- size = decl_constant_value (size);
+ size = integral_constant_value (size);
/* Normally, the array-bound will be a constant. */
if (TREE_CODE (size) == INTEGER_CST)
@@ -6177,7 +6621,7 @@ compute_array_index_type (tree name, tree size)
if (INT_CST_LT (size, integer_zero_node))
{
if (name)
- error ("size of array `%D' is negative", name);
+ error ("size of array %qD is negative", name);
else
error ("size of array is negative");
size = integer_one_node;
@@ -6187,7 +6631,7 @@ compute_array_index_type (tree name, tree size)
else if (integer_zerop (size) && pedantic && !in_system_header)
{
if (name)
- pedwarn ("ISO C++ forbids zero-size array `%D'", name);
+ pedwarn ("ISO C++ forbids zero-size array %qD", name);
else
pedwarn ("ISO C++ forbids zero-size array");
}
@@ -6196,15 +6640,16 @@ compute_array_index_type (tree name, tree size)
{
/* `(int) &fn' is not a valid array bound. */
if (name)
- error ("size of array `%D' is not an integral constant-expression",
- name);
+ error ("size of array %qD is not an integral constant-expression",
+ name);
else
error ("size of array is not an integral constant-expression");
+ size = integer_one_node;
}
else if (pedantic)
{
if (name)
- pedwarn ("ISO C++ forbids variable-size array `%D'", name);
+ pedwarn ("ISO C++ forbids variable-size array %qD", name);
else
pedwarn ("ISO C++ forbids variable-size array");
}
@@ -6214,19 +6659,28 @@ compute_array_index_type (tree name, tree size)
itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node);
else
{
+ HOST_WIDE_INT saved_processing_template_decl;
+
/* Compute the index of the largest element in the array. It is
- one less than the number of elements in the array. */
- itype
- = fold (cp_build_binary_op (MINUS_EXPR,
- cp_convert (ssizetype, size),
- cp_convert (ssizetype, integer_one_node)));
+ one less than the number of elements in the array. We save
+ and restore PROCESSING_TEMPLATE_DECL so that computations in
+ cp_build_binary_op will be appropriately folded. */
+ saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ itype = cp_build_binary_op (MINUS_EXPR,
+ cp_convert (ssizetype, size),
+ cp_convert (ssizetype, integer_one_node));
+ itype = fold (itype);
+ processing_template_decl = saved_processing_template_decl;
+
if (!TREE_CONSTANT (itype))
/* A variable sized array. */
itype = variable_size (itype);
/* Make sure that there was no overflow when creating to a signed
- index type. (For example, on a 32-bit machine, an array with
- size 2^32 - 1 is too big.) */
- else if (TREE_OVERFLOW (itype))
+ index type. (For example, on a 32-bit machine, an array with
+ size 2^32 - 1 is too big.) */
+ else if (TREE_CODE (itype) == INTEGER_CST
+ && TREE_OVERFLOW (itype))
{
error ("overflow in array dimension");
TREE_OVERFLOW (itype) = 0;
@@ -6242,40 +6696,20 @@ compute_array_index_type (tree name, tree size)
unqualified name, NULL_TREE is returned. */
tree
-get_scope_of_declarator (tree declarator)
+get_scope_of_declarator (const cp_declarator *declarator)
{
- if (!declarator)
- return NULL_TREE;
-
- switch (TREE_CODE (declarator))
- {
- case CALL_EXPR:
- case ARRAY_REF:
- case INDIRECT_REF:
- case ADDR_EXPR:
- /* For any of these, the main declarator is the first operand. */
- return get_scope_of_declarator (TREE_OPERAND
- (declarator, 0));
-
- case SCOPE_REF:
- /* For a pointer-to-member, continue descending. */
- if (TREE_CODE (TREE_OPERAND (declarator, 1))
- == INDIRECT_REF)
- return get_scope_of_declarator (TREE_OPERAND
- (declarator, 1));
- /* Otherwise, if the declarator-id is a SCOPE_REF, the scope in
- which the declaration occurs is the first operand. */
- return TREE_OPERAND (declarator, 0);
-
- case TREE_LIST:
- /* Attributes to be applied. The declarator is TREE_VALUE. */
- return get_scope_of_declarator (TREE_VALUE (declarator));
-
- default:
- /* Otherwise, we have a declarator-id which is not a qualified
- name; the entity will be declared in the current scope. */
- return NULL_TREE;
- }
+ while (declarator && declarator->kind != cdk_id)
+ declarator = declarator->declarator;
+
+ /* If the declarator-id is a SCOPE_REF, the scope in which the
+ declaration occurs is the first operand. */
+ if (declarator
+ && declarator->u.id.qualifying_scope)
+ return declarator->u.id.qualifying_scope;
+
+ /* Otherwise, the declarator is not a qualified name; the entity will
+ be declared in the current scope. */
+ return NULL_TREE;
}
/* Returns an ARRAY_TYPE for an array with SIZE elements of the
@@ -6322,7 +6756,7 @@ create_array_type_for_decl (tree name, tree type, tree size)
if (error_msg)
{
if (name)
- error ("declaration of `%D' as %s", name, error_msg);
+ error ("declaration of %qD as %s", name, error_msg);
else
error ("creating %s", error_msg);
@@ -6336,10 +6770,12 @@ create_array_type_for_decl (tree name, tree type, tree size)
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
if (name)
- error ("declaration of `%D' as multidimensional array must have bounds for all dimensions except the first",
- name);
+ error ("declaration of %qD as multidimensional array must "
+ "have bounds for all dimensions except the first",
+ name);
else
- error ("multidimensional array must have bounds for all dimensions except the first");
+ error ("multidimensional array must have bounds for all "
+ "dimensions except the first");
return error_mark_node;
}
@@ -6348,20 +6784,26 @@ create_array_type_for_decl (tree name, tree type, tree size)
if (size)
itype = compute_array_index_type (name, size);
+ /* [dcl.array]
+ T is called the array element type; this type shall not be [...] an
+ abstract class type. */
+ abstract_virtuals_error (name, type);
+
return build_cplus_array_type (type, itype);
}
/* Check that it's OK to declare a function with the indicated TYPE.
SFK indicates the kind of special function (if any) that this
function is. OPTYPE is the type given in a conversion operator
- declaration. Returns the actual return type of the function; that
+ declaration, or the class type for a constructor/destructor.
+ Returns the actual return type of the function; that
may be different than TYPE if an error occurs, or for certain
special functions. */
static tree
check_special_function_return_type (special_function_kind sfk,
- tree type,
- tree optype)
+ tree type,
+ tree optype)
{
switch (sfk)
{
@@ -6369,26 +6811,35 @@ check_special_function_return_type (special_function_kind sfk,
if (type)
error ("return type specification for constructor invalid");
- type = void_type_node;
+ if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
+ type = build_pointer_type (optype);
+ else
+ type = void_type_node;
break;
case sfk_destructor:
if (type)
error ("return type specification for destructor invalid");
- type = void_type_node;
+ /* We can't use the proper return type here because we run into
+ problems with ambiguous bases and covariant returns.
+ Java classes are left unchanged because (void *) isn't a valid
+ Java type, and we don't want to change the Java ABI. */
+ if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
+ type = build_pointer_type (void_type_node);
+ else
+ type = void_type_node;
break;
case sfk_conversion:
if (type && !same_type_p (type, optype))
- error ("operator `%T' declared to return `%T'", optype, type);
+ error ("operator %qT declared to return %qT", optype, type);
else if (type)
- pedwarn ("return type specified for `operator %T'", optype);
+ pedwarn ("return type specified for %<operator %T%>", optype);
type = optype;
break;
default:
- abort ();
- break;
+ gcc_unreachable ();
}
return type;
@@ -6397,7 +6848,7 @@ check_special_function_return_type (special_function_kind sfk,
/* A variable or data member (whose unqualified name is IDENTIFIER)
has been declared with the indicated TYPE. If the TYPE is not
acceptable, issue an error message and return a type to use for
- error-recovery purposes. */
+ error-recovery purposes. */
tree
check_var_type (tree identifier, tree type)
@@ -6408,15 +6859,14 @@ check_var_type (tree identifier, tree type)
error ("unnamed variable or field declared void");
else if (TREE_CODE (identifier) == IDENTIFIER_NODE)
{
- if (IDENTIFIER_OPNAME_P (identifier))
- abort ();
- error ("variable or field `%E' declared void", identifier);
+ gcc_assert (!IDENTIFIER_OPNAME_P (identifier));
+ error ("variable or field %qE declared void", identifier);
}
else
error ("variable or field declared void");
- type = integer_type_node;
+ type = error_mark_node;
}
-
+
return type;
}
@@ -6457,33 +6907,33 @@ check_var_type (tree identifier, tree type)
void S::f() { ... }
when grokdeclarator is called for `S::f', the CURRENT_CLASS_TYPE
- should not be `S'. */
+ should not be `S'.
+
+ Returns a DECL (if a declarator is present), a TYPE (if there is no
+ declarator, in cases like "struct S;"), or the ERROR_MARK_NODE if an
+ error occurs. */
tree
-grokdeclarator (tree declarator,
- tree declspecs,
- enum decl_context decl_context,
- int initialized,
- tree* attrlist)
-{
- RID_BIT_TYPE specbits;
- int nclasses = 0;
- tree spec;
+grokdeclarator (const cp_declarator *declarator,
+ const cp_decl_specifier_seq *declspecs,
+ enum decl_context decl_context,
+ int initialized,
+ tree* attrlist)
+{
tree type = NULL_TREE;
int longlong = 0;
- int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
- int extern_langp = 0;
- tree dependant_name = NULL_TREE;
-
+ tree dependent_name = NULL_TREE;
+
tree typedef_decl = NULL_TREE;
- const char *name;
+ const char *name = NULL;
tree typedef_type = NULL_TREE;
- int funcdef_flag = 0;
- enum tree_code innermost_code = ERROR_MARK;
+ /* True if this declarator is a function definition. */
+ bool funcdef_flag = false;
+ cp_declarator_kind innermost_code = cdk_error;
int bitfield = 0;
#if 0
/* See the code below that used this. */
@@ -6496,307 +6946,214 @@ grokdeclarator (tree declarator,
special_function_kind sfk = sfk_none;
tree dname = NULL_TREE;
- tree ctype = current_class_type;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
- tree quals = NULL_TREE;
+ /* cv-qualifiers that apply to the declarator, for a declaration of
+ a member function. */
+ cp_cv_quals memfn_quals = TYPE_UNQUALIFIED;
+ /* cv-qualifiers that apply to the type specified by the DECLSPECS. */
+ int type_quals;
tree raises = NULL_TREE;
int template_count = 0;
- tree in_namespace = NULL_TREE;
tree returned_attrs = NULL_TREE;
- tree scope = NULL_TREE;
tree parms = NULL_TREE;
+ const cp_declarator *id_declarator;
+ /* The unqualified name of the declarator; either an
+ IDENTIFIER_NODE, BIT_NOT_EXPR, or TEMPLATE_ID_EXPR. */
+ tree unqualified_id;
+ /* The class type, if any, in which this entity is located,
+ or NULL_TREE if none. Note that this value may be different from
+ the current class type; for example if an attempt is made to declare
+ "A::f" inside "B", this value will be "A". */
+ tree ctype = current_class_type;
+ /* The NAMESPACE_DECL for the namespace in which this entity is
+ located. If an unqualified name is used to declare the entity,
+ this value will be NULL_TREE, even if the entity is located at
+ namespace scope. */
+ tree in_namespace = NULL_TREE;
+ cp_storage_class storage_class;
+ bool unsigned_p, signed_p, short_p, long_p, thread_p;
+ bool type_was_error_mark_node = false;
+
+ signed_p = declspecs->specs[(int)ds_signed];
+ unsigned_p = declspecs->specs[(int)ds_unsigned];
+ short_p = declspecs->specs[(int)ds_short];
+ long_p = declspecs->specs[(int)ds_long];
+ longlong = declspecs->specs[(int)ds_long] >= 2;
+ thread_p = declspecs->specs[(int)ds_thread];
- RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
- funcdef_flag = 1, decl_context = NORMAL;
+ funcdef_flag = true, decl_context = NORMAL;
else if (decl_context == MEMFUNCDEF)
- funcdef_flag = -1, decl_context = FIELD;
+ funcdef_flag = true, decl_context = FIELD;
else if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
- {
- tree *next = &declarator;
- tree decl;
- name = NULL;
-
- while (next && *next)
- {
- decl = *next;
- switch (TREE_CODE (decl))
- {
- case TREE_LIST:
- /* For attributes. */
- next = &TREE_VALUE (decl);
- break;
-
- case COND_EXPR:
- ctype = NULL_TREE;
- next = &TREE_OPERAND (decl, 0);
- break;
+ for (id_declarator = declarator;
+ id_declarator;
+ id_declarator = id_declarator->declarator)
+ {
+ if (id_declarator->kind != cdk_id)
+ innermost_code = id_declarator->kind;
- case BIT_NOT_EXPR: /* For C++ destructors! */
+ switch (id_declarator->kind)
+ {
+ case cdk_function:
+ if (id_declarator->declarator
+ && id_declarator->declarator->kind == cdk_id)
{
- tree name = TREE_OPERAND (decl, 0);
- tree rename = NULL_TREE;
-
- my_friendly_assert (flags == NO_SPECIAL, 152);
- flags = DTOR_FLAG;
- sfk = sfk_destructor;
- if (TYPE_P (name))
- TREE_OPERAND (decl, 0) = name = constructor_name (name);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
- if (ctype == NULL_TREE)
- {
- if (current_class_type == NULL_TREE)
- {
- error ("destructors must be member functions");
- flags = NO_SPECIAL;
- }
- else
- {
- tree t = constructor_name (current_class_type);
- if (t != name)
- rename = t;
- }
- }
- else
- {
- tree t = constructor_name (ctype);
- if (t != name)
- rename = t;
- }
-
- if (rename)
- {
- error ("destructor `%T' must match class name `%T'",
- name, rename);
- TREE_OPERAND (decl, 0) = rename;
- }
- next = &name;
+ sfk = id_declarator->declarator->u.id.sfk;
+ if (sfk == sfk_destructor)
+ flags = DTOR_FLAG;
}
- break;
-
- case ADDR_EXPR: /* C++ reference declaration */
- /* Fall through. */
- case ARRAY_REF:
- case INDIRECT_REF:
- ctype = NULL_TREE;
- innermost_code = TREE_CODE (decl);
- next = &TREE_OPERAND (decl, 0);
- break;
-
- case CALL_EXPR:
- innermost_code = TREE_CODE (decl);
- if (decl_context == FIELD && ctype == NULL_TREE)
- ctype = current_class_type;
- if (ctype
- && TREE_OPERAND (decl, 0)
- && (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL
- && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 0)),
- ctype)))
- TREE_OPERAND (decl, 0) = constructor_name (ctype);
- next = &TREE_OPERAND (decl, 0);
- decl = *next;
- if (ctype != NULL_TREE
- && decl != NULL_TREE && flags != DTOR_FLAG
- && constructor_name_p (decl, ctype))
- {
- sfk = sfk_constructor;
- ctor_return_type = ctype;
- }
- ctype = NULL_TREE;
- break;
+ break;
- case TEMPLATE_ID_EXPR:
+ case cdk_id:
+ {
+ tree qualifying_scope = id_declarator->u.id.qualifying_scope;
+ tree decl = id_declarator->u.id.unqualified_name;
+ if (!decl)
+ break;
+ if (qualifying_scope)
{
- tree fns = TREE_OPERAND (decl, 0);
-
- dname = fns;
- if (TREE_CODE (dname) == COMPONENT_REF)
- dname = TREE_OPERAND (dname, 1);
- if (TREE_CODE (dname) != IDENTIFIER_NODE)
+ if (at_function_scope_p ())
{
- my_friendly_assert (is_overloaded_fn (dname),
- 19990331);
- dname = DECL_NAME (get_first_fn (dname));
+ /* [dcl.meaning]
+
+ A declarator-id shall not be qualified except
+ for ...
+
+ None of the cases are permitted in block
+ scope. */
+ if (qualifying_scope == global_namespace)
+ error ("invalid use of qualified-name %<::%D%>",
+ decl);
+ else if (TYPE_P (qualifying_scope))
+ error ("invalid use of qualified-name %<%T::%D%>",
+ qualifying_scope, decl);
+ else
+ error ("invalid use of qualified-name %<%D::%D%>",
+ qualifying_scope, decl);
+ return error_mark_node;
}
+ else if (TYPE_P (qualifying_scope))
+ {
+ ctype = qualifying_scope;
+ if (innermost_code != cdk_function
+ && current_class_type
+ && !UNIQUELY_DERIVED_FROM_P (ctype,
+ current_class_type))
+ {
+ error ("type %qT is not derived from type %qT",
+ ctype, current_class_type);
+ return error_mark_node;
+ }
+ }
+ else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
+ in_namespace = qualifying_scope;
}
- /* Fall through. */
-
- case IDENTIFIER_NODE:
- if (TREE_CODE (decl) == IDENTIFIER_NODE)
- dname = decl;
-
- next = 0;
-
- if (C_IS_RESERVED_WORD (dname))
- {
- error ("declarator-id missing; using reserved word `%D'",
- dname);
- name = IDENTIFIER_POINTER (dname);
- }
- else if (!IDENTIFIER_TYPENAME_P (dname))
- name = IDENTIFIER_POINTER (dname);
- else
+ switch (TREE_CODE (decl))
{
- my_friendly_assert (flags == NO_SPECIAL, 154);
- flags = TYPENAME_FLAG;
- ctor_return_type = TREE_TYPE (dname);
- sfk = sfk_conversion;
- if (is_typename_at_global_scope (dname))
- name = IDENTIFIER_POINTER (dname);
- else
- name = "<invalid operator>";
- }
- break;
-
- /* C++ extension */
- case SCOPE_REF:
- {
- /* Perform error checking, and decide on a ctype. */
- tree cname = TREE_OPERAND (decl, 0);
- if (cname == NULL_TREE)
- ctype = NULL_TREE;
- else if (TREE_CODE (cname) == NAMESPACE_DECL)
- {
- ctype = NULL_TREE;
- in_namespace = TREE_OPERAND (decl, 0);
- }
- else if (! is_aggr_type (cname, 1))
- ctype = NULL_TREE;
- /* Must test TREE_OPERAND (decl, 1), in case user gives
- us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */
- else if (TREE_OPERAND (decl, 1)
- && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
- ctype = cname;
- else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
- || TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ case BIT_NOT_EXPR:
{
- /* This might be declaring a member of a template
- parm to be a friend. */
- ctype = cname;
- dependant_name = TREE_OPERAND (decl, 1);
- }
- else if (ctype == NULL_TREE)
- ctype = cname;
- else if (TREE_COMPLEXITY (decl) == current_class_depth)
- ;
- else
- {
- if (! UNIQUELY_DERIVED_FROM_P (cname, ctype))
+ tree type;
+
+ if (innermost_code != cdk_function)
{
- error ("type `%T' is not derived from type `%T'",
- cname, ctype);
- ctype = NULL_TREE;
+ error ("declaration of %qD as non-function", decl);
+ return error_mark_node;
}
- else
- ctype = cname;
+ else if (!qualifying_scope
+ && !(current_class_type && at_class_scope_p ()))
+ {
+ error ("declaration of %qD as non-member", decl);
+ return error_mark_node;
+ }
+
+ type = TREE_OPERAND (decl, 0);
+ name = IDENTIFIER_POINTER (constructor_name (type));
+ dname = decl;
}
+ break;
- /* It is valid to write:
-
- class C { void f(); };
- typedef C D;
- void D::f();
-
- The standard is not clear about whether `typedef const C D' is
- legal; as of 2002-09-15 the committee is considering
- that question. EDG 3.0 allows that syntax.
- Therefore, we do as well. */
- if (ctype)
- ctype = TYPE_MAIN_VARIANT (ctype);
- /* Update the declarator so that when we process it
- again the correct type is present. */
- TREE_OPERAND (decl, 0) = ctype;
-
- if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
- && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 1)),
- ctype))
- TREE_OPERAND (decl, 1) = constructor_name (ctype);
- next = &TREE_OPERAND (decl, 1);
- decl = *next;
- if (ctype)
+ case TEMPLATE_ID_EXPR:
{
- tree name = decl;
+ tree fns = TREE_OPERAND (decl, 0);
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- name = TREE_OPERAND (name, 0);
-
- if (!constructor_name_p (decl, ctype))
- ;
- else if (decl == name)
+ dname = fns;
+ if (TREE_CODE (dname) != IDENTIFIER_NODE)
{
- sfk = sfk_constructor;
- ctor_return_type = ctype;
- }
- else
- {
- sfk = sfk_destructor;
- ctor_return_type = ctype;
- flags = DTOR_FLAG;
- TREE_OPERAND (decl, 0) = constructor_name (ctype);
- next = &TREE_OPERAND (decl, 0);
+ gcc_assert (is_overloaded_fn (dname));
+ dname = DECL_NAME (get_first_fn (dname));
}
}
- }
- break;
+ /* Fall through. */
- case ERROR_MARK:
- next = 0;
- break;
+ case IDENTIFIER_NODE:
+ if (TREE_CODE (decl) == IDENTIFIER_NODE)
+ dname = decl;
+
+ if (C_IS_RESERVED_WORD (dname))
+ {
+ error ("declarator-id missing; using reserved word %qD",
+ dname);
+ name = IDENTIFIER_POINTER (dname);
+ }
+ else if (!IDENTIFIER_TYPENAME_P (dname))
+ name = IDENTIFIER_POINTER (dname);
+ else
+ {
+ gcc_assert (flags == NO_SPECIAL);
+ flags = TYPENAME_FLAG;
+ ctor_return_type = TREE_TYPE (dname);
+ sfk = sfk_conversion;
+ if (is_typename_at_global_scope (dname))
+ name = IDENTIFIER_POINTER (dname);
+ else
+ name = "<invalid operator>";
+ }
+ break;
- case TYPE_DECL:
- /* Parse error puts this typespec where
- a declarator should go. */
- error ("`%T' specified as declarator-id", DECL_NAME (decl));
- if (TREE_TYPE (decl) == current_class_type)
- error (" perhaps you want `%T' for a constructor",
- current_class_name);
- dname = DECL_NAME (decl);
- name = IDENTIFIER_POINTER (dname);
-
- /* Avoid giving two errors for this. */
- IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
-
- declspecs = tree_cons (NULL_TREE, integer_type_node, declspecs);
- *next = dname;
- next = 0;
+ default:
+ gcc_unreachable ();
+ }
break;
- case BASELINK:
- next = &BASELINK_FUNCTIONS (decl);
+ case cdk_array:
+ case cdk_pointer:
+ case cdk_reference:
+ case cdk_ptrmem:
break;
- case TEMPLATE_DECL:
- /* Sometimes, we see a template-name used as part of a
- decl-specifier like in
- std::allocator alloc;
- Handle that gracefully. */
- error ("invalid use of template-name '%E' in a declarator", decl);
+ case cdk_error:
return error_mark_node;
- break;
-
+
default:
- my_friendly_assert (0, 20020917);
+ gcc_unreachable ();
}
- }
- }
+ }
+ if (id_declarator->kind == cdk_id)
+ break;
+ }
- /* A function definition's declarator must have the form of
- a function declarator. */
+ /* [dcl.fct.edf]
- if (funcdef_flag && innermost_code != CALL_EXPR)
- return 0;
+ The declarator in a function-definition shall have the form
+ D1 ( parameter-declaration-clause) ... */
+ if (funcdef_flag && innermost_code != cdk_function)
+ {
+ error ("function definition does not declare parameters");
+ return error_mark_node;
+ }
if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
- && innermost_code != CALL_EXPR
- && ! (ctype && declspecs == NULL_TREE))
+ && innermost_code != cdk_function
+ && ! (ctype && !declspecs->any_specifiers_p))
{
- error ("declaration of `%D' as non-function", dname);
- return void_type_node;
+ error ("declaration of %qD as non-function", dname);
+ return error_mark_node;
}
/* Anything declared one level down from the top level
@@ -6825,145 +7182,42 @@ grokdeclarator (tree declarator,
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
- /* Look through the decl specs and record which ones appear.
- Some typespecs are defined as built-in typenames.
- Others, the ones that are modifiers of other types,
- are represented by bits in SPECBITS: set the bits for
- the modifiers that appear. Storage class keywords are also in SPECBITS.
-
- If there is a typedef name or a type, store the type in TYPE.
- This includes builtin typedefs such as `int'.
-
- Set EXPLICIT_INT if the type is `int' or `char' and did not
- come from a user typedef.
-
- Set LONGLONG if `long' is mentioned twice.
-
- For C++, constructors and destructors have their own fast treatment. */
-
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
+ /* If there were multiple types specified in the decl-specifier-seq,
+ issue an error message. */
+ if (declspecs->multiple_types_p)
{
- int i;
- tree id;
-
- /* Certain parse errors slip through. For example,
- `int class;' is not caught by the parser. Try
- weakly to recover here. */
- if (TREE_CODE (spec) != TREE_LIST)
- return 0;
-
- id = TREE_VALUE (spec);
-
- /* If the entire declaration is itself tagged as deprecated then
- suppress reports of deprecated items. */
- if (!adding_implicit_members && id && TREE_DEPRECATED (id))
- {
- if (deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (id);
- }
-
- if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- if (id == ridpointers[(int) RID_INT]
- || id == ridpointers[(int) RID_CHAR]
- || id == ridpointers[(int) RID_BOOL]
- || id == ridpointers[(int) RID_WCHAR])
- {
- if (type)
- {
- if (id == ridpointers[(int) RID_BOOL])
- error ("`bool' is now a keyword");
- else
- error ("extraneous `%T' ignored", id);
- }
- else
- {
- if (id == ridpointers[(int) RID_INT])
- explicit_int = 1;
- else if (id == ridpointers[(int) RID_CHAR])
- explicit_char = 1;
- type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
- }
- goto found;
- }
- /* C++ aggregate types. */
- if (IDENTIFIER_HAS_TYPE_VALUE (id))
- {
- if (type)
- error ("multiple declarations `%T' and `%T'", type, id);
- else
- type = IDENTIFIER_TYPE_VALUE (id);
- goto found;
- }
-
- for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++)
- {
- if (ridpointers[i] == id)
- {
- if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
- {
- if (pedantic && ! in_system_header && warn_long_long)
- pedwarn ("ISO C++ does not support `long long'");
- if (longlong)
- error ("`long long long' is too long for GCC");
- else
- longlong = 1;
- }
- else if (RIDBIT_SETP (i, specbits))
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
-
- /* Diagnose "__thread extern" or "__thread static". */
- if (RIDBIT_SETP (RID_THREAD, specbits))
- {
- if (i == (int)RID_EXTERN)
- error ("`__thread' before `extern'");
- else if (i == (int)RID_STATIC)
- error ("`__thread' before `static'");
- }
-
- if (i == (int)RID_EXTERN
- && TREE_PURPOSE (spec) == error_mark_node)
- /* This extern was part of a language linkage. */
- extern_langp = 1;
-
- RIDBIT_SET (i, specbits);
- goto found;
- }
- }
- }
- else if (TREE_CODE (id) == TYPE_DECL)
- {
- if (type)
- error ("multiple declarations `%T' and `%T'", type,
- TREE_TYPE (id));
- else
- {
- type = TREE_TYPE (id);
- TREE_VALUE (spec) = type;
- typedef_decl = id;
- }
- goto found;
- }
- if (type)
- error ("two or more data types in declaration of `%s'", name);
- else if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- tree t = lookup_name (id, 1);
- if (!t || TREE_CODE (t) != TYPE_DECL)
- error ("`%s' fails to be a typedef or built in type",
- IDENTIFIER_POINTER (id));
- else
- {
- type = TREE_TYPE (t);
- typedef_decl = t;
- }
- }
- else if (id != error_mark_node)
- /* Can't change CLASS nodes into RECORD nodes here! */
- type = id;
+ error ("two or more data types in declaration of %qs", name);
+ return error_mark_node;
+ }
- found: ;
+ /* Extract the basic type from the decl-specifier-seq. */
+ type = declspecs->type;
+ if (type == error_mark_node)
+ {
+ type = NULL_TREE;
+ type_was_error_mark_node = true;
+ }
+ /* If the entire declaration is itself tagged as deprecated then
+ suppress reports of deprecated items. */
+ if (type && TREE_DEPRECATED (type)
+ && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (type);
+ if (type && TREE_CODE (type) == TYPE_DECL)
+ {
+ typedef_decl = type;
+ type = TREE_TYPE (typedef_decl);
+ }
+ /* No type at all: default to `int', and set DEFAULTED_INT
+ because it was not a user-defined typedef. */
+ if (type == NULL_TREE && (signed_p || unsigned_p || long_p || short_p))
+ {
+ /* These imply 'int'. */
+ type = integer_type_node;
+ defaulted_int = 1;
}
+ /* Gather flags. */
+ explicit_int = declspecs->explicit_int_p;
+ explicit_char = declspecs->explicit_char_p;
#if 0
/* See the code below that used this. */
@@ -6972,19 +7226,9 @@ grokdeclarator (tree declarator,
#endif
typedef_type = type;
- /* No type at all: default to `int', and set DEFAULTED_INT
- because it was not a user-defined typedef. */
- if (type == NULL_TREE
- && (RIDBIT_SETP (RID_SIGNED, specbits)
- || RIDBIT_SETP (RID_UNSIGNED, specbits)
- || RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits)))
- {
- /* These imply 'int'. */
- type = integer_type_node;
- defaulted_int = 1;
- }
+ if (sfk != sfk_conversion)
+ ctor_return_type = ctype;
if (sfk != sfk_none)
type = check_special_function_return_type (sfk, type,
@@ -7004,66 +7248,59 @@ grokdeclarator (tree declarator,
&& in_namespace == NULL_TREE
&& current_namespace == global_namespace);
- if (in_system_header || flag_ms_extensions)
+ if (type_was_error_mark_node)
+ /* We've already issued an error, don't complain more. */;
+ else if (in_system_header || flag_ms_extensions)
/* Allow it, sigh. */;
else if (pedantic || ! is_main)
- pedwarn ("ISO C++ forbids declaration of `%s' with no type",
- name);
+ pedwarn ("ISO C++ forbids declaration of %qs with no type", name);
else if (warn_return_type)
- warning ("ISO C++ forbids declaration of `%s' with no type",
- name);
+ warning (0, "ISO C++ forbids declaration of %qs with no type", name);
type = integer_type_node;
}
-
+
ctype = NULL_TREE;
/* Now process the modifiers that were specified
and check for invalid combinations. */
/* Long double is a special combination. */
-
- if (RIDBIT_SETP (RID_LONG, specbits)
- && TYPE_MAIN_VARIANT (type) == double_type_node)
+ if (long_p && !longlong && TYPE_MAIN_VARIANT (type) == double_type_node)
{
- RIDBIT_RESET (RID_LONG, specbits);
+ long_p = false;
type = build_qualified_type (long_double_type_node,
cp_type_quals (type));
}
/* Check all other uses of type modifiers. */
- if (RIDBIT_SETP (RID_UNSIGNED, specbits)
- || RIDBIT_SETP (RID_SIGNED, specbits)
- || RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits))
+ if (unsigned_p || signed_p || long_p || short_p)
{
int ok = 0;
- if (TREE_CODE (type) == REAL_TYPE)
- error ("short, signed or unsigned invalid for `%s'", name);
- else if (TREE_CODE (type) != INTEGER_TYPE)
- error ("long, short, signed or unsigned invalid for `%s'", name);
- else if (RIDBIT_SETP (RID_LONG, specbits)
- && RIDBIT_SETP (RID_SHORT, specbits))
- error ("long and short specified together for `%s'", name);
- else if ((RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits))
- && explicit_char)
- error ("long or short specified with char for `%s'", name);
- else if ((RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits))
- && TREE_CODE (type) == REAL_TYPE)
- error ("long or short specified with floating type for `%s'", name);
- else if (RIDBIT_SETP (RID_SIGNED, specbits)
- && RIDBIT_SETP (RID_UNSIGNED, specbits))
- error ("signed and unsigned given together for `%s'", name);
+ if ((signed_p || unsigned_p) && TREE_CODE (type) != INTEGER_TYPE)
+ error ("%<signed%> or %<unsigned%> invalid for %qs", name);
+ else if (signed_p && unsigned_p)
+ error ("%<signed%> and %<unsigned%> specified together for %qs", name);
+ else if (longlong && TREE_CODE (type) != INTEGER_TYPE)
+ error ("%<long long%> invalid for %qs", name);
+ else if (long_p && TREE_CODE (type) == REAL_TYPE)
+ error ("%<long%> invalid for %qs", name);
+ else if (short_p && TREE_CODE (type) == REAL_TYPE)
+ error ("%<short%> invalid for %qs", name);
+ else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
+ error ("%<long%> or %<short%> invalid for %qs", name);
+ else if ((long_p || short_p) && explicit_char)
+ error ("%<long%> or %<short%> specified with char for %qs", name);
+ else if (long_p && short_p)
+ error ("%<long%> and %<short%> specified together for %qs", name);
else
{
ok = 1;
if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
{
- pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
+ pedwarn ("long, short, signed or unsigned used invalidly for %qs",
name);
if (flag_pedantic_errors)
ok = 0;
@@ -7073,24 +7310,17 @@ grokdeclarator (tree declarator,
/* Discard the type modifiers if they are invalid. */
if (! ok)
{
- RIDBIT_RESET (RID_UNSIGNED, specbits);
- RIDBIT_RESET (RID_SIGNED, specbits);
- RIDBIT_RESET (RID_LONG, specbits);
- RIDBIT_RESET (RID_SHORT, specbits);
+ unsigned_p = false;
+ signed_p = false;
+ long_p = false;
+ short_p = false;
longlong = 0;
}
}
- if (RIDBIT_SETP (RID_COMPLEX, specbits)
- && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
- {
- error ("complex invalid for `%s'", name);
- RIDBIT_RESET (RID_COMPLEX, specbits);
- }
-
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
- if (RIDBIT_SETP (RID_UNSIGNED, specbits)
+ if (unsigned_p
/* [class.bit]
It is implementation-defined whether a plain (neither
@@ -7100,21 +7330,20 @@ grokdeclarator (tree declarator,
Naturally, we extend this to long long as well. Note that
this does not include wchar_t. */
|| (bitfield && !flag_signed_bitfields
- && RIDBIT_NOTSETP (RID_SIGNED, specbits)
+ && !signed_p
/* A typedef for plain `int' without `signed' can be
controlled just like plain `int', but a typedef for
`signed int' cannot be so controlled. */
&& !(typedef_decl
&& C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == CHAR_TYPE)
+ && TREE_CODE (type) == INTEGER_TYPE
&& !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
{
if (longlong)
type = long_long_unsigned_type_node;
- else if (RIDBIT_SETP (RID_LONG, specbits))
+ else if (long_p)
type = long_unsigned_type_node;
- else if (RIDBIT_SETP (RID_SHORT, specbits))
+ else if (short_p)
type = short_unsigned_type_node;
else if (type == char_type_node)
type = unsigned_char_type_node;
@@ -7123,28 +7352,26 @@ grokdeclarator (tree declarator,
else
type = unsigned_type_node;
}
- else if (RIDBIT_SETP (RID_SIGNED, specbits)
- && type == char_type_node)
+ else if (signed_p && type == char_type_node)
type = signed_char_type_node;
else if (longlong)
type = long_long_integer_type_node;
- else if (RIDBIT_SETP (RID_LONG, specbits))
+ else if (long_p)
type = long_integer_type_node;
- else if (RIDBIT_SETP (RID_SHORT, specbits))
+ else if (short_p)
type = short_integer_type_node;
- if (RIDBIT_SETP (RID_COMPLEX, specbits))
+ if (declspecs->specs[(int)ds_complex])
{
+ if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
+ error ("complex invalid for %qs", name);
/* If we just have "complex", it is equivalent to
"complex double", but if any modifiers at all are specified it is
the complex form of TYPE. E.g, "complex short" is
"complex short int". */
- if (defaulted_int && ! longlong
- && ! (RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits)
- || RIDBIT_SETP (RID_SIGNED, specbits)
- || RIDBIT_SETP (RID_UNSIGNED, specbits)))
+ else if (defaulted_int && ! longlong
+ && ! (long_p || short_p || signed_p || unsigned_p))
type = complex_double_type_node;
else if (type == integer_type_node)
type = complex_integer_type_node;
@@ -7159,67 +7386,72 @@ grokdeclarator (tree declarator,
}
type_quals = TYPE_UNQUALIFIED;
- if (RIDBIT_SETP (RID_CONST, specbits))
+ if (declspecs->specs[(int)ds_const])
type_quals |= TYPE_QUAL_CONST;
- if (RIDBIT_SETP (RID_VOLATILE, specbits))
+ if (declspecs->specs[(int)ds_volatile])
type_quals |= TYPE_QUAL_VOLATILE;
- if (RIDBIT_SETP (RID_RESTRICT, specbits))
+ if (declspecs->specs[(int)ds_restrict])
type_quals |= TYPE_QUAL_RESTRICT;
if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
- error ("qualifiers are not allowed on declaration of `operator %T'",
- ctor_return_type);
+ error ("qualifiers are not allowed on declaration of %<operator %T%>",
+ ctor_return_type);
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals != TYPE_UNQUALIFIED)
+ {
+ /* This was an error in C++98 (cv-qualifiers cannot be added to
+ a function type), but DR 295 makes the code well-formed by
+ dropping the extra qualifiers. */
+ if (pedantic)
+ {
+ tree bad_type = build_qualified_type (type, type_quals);
+ pedwarn ("ignoring %qV qualifiers added to function type %qT",
+ bad_type, type);
+ }
+ type_quals = TYPE_UNQUALIFIED;
+ }
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
(type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
- ? tf_ignore_bad_quals : 0) | tf_error | tf_warning));
+ ? tf_ignore_bad_quals : 0) | tf_warning_or_error));
/* We might have ignored or rejected some of the qualifiers. */
type_quals = cp_type_quals (type);
-
+
staticp = 0;
- inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
- virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
- RIDBIT_RESET (RID_VIRTUAL, specbits);
- explicitp = RIDBIT_SETP (RID_EXPLICIT, specbits) != 0;
- RIDBIT_RESET (RID_EXPLICIT, specbits);
+ inlinep = !! declspecs->specs[(int)ds_inline];
+ virtualp = !! declspecs->specs[(int)ds_virtual];
+ explicitp = !! declspecs->specs[(int)ds_explicit];
- if (RIDBIT_SETP (RID_STATIC, specbits))
+ storage_class = declspecs->storage_class;
+ if (storage_class == sc_static)
staticp = 1 + (decl_context == FIELD);
if (virtualp && staticp == 2)
{
- error ("member `%D' cannot be declared both virtual and static", dname);
- RIDBIT_RESET (RID_STATIC, specbits);
+ error ("member %qD cannot be declared both virtual and static", dname);
+ storage_class = sc_none;
staticp = 0;
}
- friendp = RIDBIT_SETP (RID_FRIEND, specbits);
- RIDBIT_RESET (RID_FRIEND, specbits);
+ friendp = !! declspecs->specs[(int)ds_friend];
- if (dependant_name && !friendp)
+ if (dependent_name && !friendp)
{
- error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
- return void_type_node;
+ error ("%<%T::%D%> is not a valid declarator", ctype, dependent_name);
+ return error_mark_node;
}
-
- /* Warn if two storage classes are given. Default to `auto'. */
- if (RIDBIT_ANY_SET (specbits))
+ /* Issue errors about use of storage classes for parameters. */
+ if (decl_context == PARM)
{
- if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
- if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
- if (RIDBIT_SETP (RID_THREAD, specbits)) nclasses++;
- if (decl_context == PARM && nclasses > 0)
- error ("storage class specifiers invalid in parameter declarations");
- if (RIDBIT_SETP (RID_TYPEDEF, specbits))
+ if (declspecs->specs[(int)ds_typedef])
{
- if (decl_context == PARM)
- error ("typedef declaration invalid in parameter declaration");
- nclasses++;
+ error ("typedef declaration invalid in parameter declaration");
+ return error_mark_node;
}
- if (RIDBIT_SETP (RID_AUTO, specbits)) nclasses++;
- if (RIDBIT_SETP (RID_REGISTER, specbits)) nclasses++;
- if (!nclasses && !friendp && extern_langp)
- nclasses++;
+ else if (storage_class == sc_static
+ || storage_class == sc_extern
+ || thread_p)
+ error ("storage class specifiers invalid in parameter declarations");
}
/* Give error if `virtual' is used outside of class declaration. */
@@ -7232,249 +7464,188 @@ grokdeclarator (tree declarator,
/* Static anonymous unions are dealt with here. */
if (staticp && decl_context == TYPENAME
- && TREE_CODE (declspecs) == TREE_LIST
- && ANON_AGGR_TYPE_P (TREE_VALUE (declspecs)))
+ && declspecs->type
+ && ANON_AGGR_TYPE_P (declspecs->type))
decl_context = FIELD;
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
-
- /* "static __thread" and "extern __thread" are allowed. */
- if (nclasses == 2
- && RIDBIT_SETP (RID_THREAD, specbits)
- && (RIDBIT_SETP (RID_EXTERN, specbits)
- || RIDBIT_SETP (RID_STATIC, specbits)))
- nclasses = 1;
-
- if (nclasses > 1)
- error ("multiple storage classes in declaration of `%s'", name);
- else if (decl_context != NORMAL && nclasses > 0)
+ if (thread_p
+ && ((storage_class
+ && storage_class != sc_extern
+ && storage_class != sc_static)
+ || declspecs->specs[(int)ds_typedef]))
+ {
+ error ("multiple storage classes in declaration of %qs", name);
+ thread_p = false;
+ }
+ if (declspecs->conflicting_specifiers_p)
+ {
+ error ("conflicting specifiers in declaration of %qs", name);
+ storage_class = sc_none;
+ }
+ else if (decl_context != NORMAL
+ && ((storage_class != sc_none
+ && storage_class != sc_mutable)
+ || thread_p))
{
if ((decl_context == PARM || decl_context == CATCHPARM)
- && (RIDBIT_SETP (RID_REGISTER, specbits)
- || RIDBIT_SETP (RID_AUTO, specbits)))
+ && (storage_class == sc_register
+ || storage_class == sc_auto))
;
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
+ else if (declspecs->specs[(int)ds_typedef])
;
else if (decl_context == FIELD
/* C++ allows static class elements. */
- && RIDBIT_SETP (RID_STATIC, specbits))
+ && storage_class == sc_static)
/* C++ also allows inlines and signed and unsigned elements,
but in those cases we don't come in here. */
;
else
{
if (decl_context == FIELD)
- {
- tree tmp = NULL_TREE;
- int op = 0;
-
- if (declarator)
- {
- /* Avoid trying to get an operand off an identifier node. */
- if (TREE_CODE (declarator) == IDENTIFIER_NODE)
- tmp = declarator;
- else
- tmp = TREE_OPERAND (declarator, 0);
- op = IDENTIFIER_OPNAME_P (tmp);
- if (IDENTIFIER_TYPENAME_P (tmp))
- {
- if (is_typename_at_global_scope (tmp))
- name = IDENTIFIER_POINTER (tmp);
- else
- name = "<invalid operator>";
- }
- }
- error ("storage class specified for %s `%s'",
- op ? "member operator" : "field",
- name);
- }
+ error ("storage class specified for %qs", name);
else
{
if (decl_context == PARM || decl_context == CATCHPARM)
- error ("storage class specified for parameter `%s'", name);
+ error ("storage class specified for parameter %qs", name);
else
error ("storage class specified for typename");
}
- RIDBIT_RESET (RID_REGISTER, specbits);
- RIDBIT_RESET (RID_AUTO, specbits);
- RIDBIT_RESET (RID_EXTERN, specbits);
- RIDBIT_RESET (RID_THREAD, specbits);
+ if (storage_class == sc_register
+ || storage_class == sc_auto
+ || storage_class == sc_extern
+ || thread_p)
+ storage_class = sc_none;
}
}
- else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
+ else if (storage_class == sc_extern && initialized
+ && !funcdef_flag)
{
if (toplevel_bindings_p ())
{
/* It's common practice (and completely valid) to have a const
be initialized and declared extern. */
if (!(type_quals & TYPE_QUAL_CONST))
- warning ("`%s' initialized and declared `extern'", name);
+ warning (0, "%qs initialized and declared %<extern%>", name);
}
else
- error ("`%s' has both `extern' and initializer", name);
+ error ("%qs has both %<extern%> and initializer", name);
}
- else if (RIDBIT_SETP (RID_EXTERN, specbits) && funcdef_flag
+ else if (storage_class == sc_extern && funcdef_flag
&& ! toplevel_bindings_p ())
- error ("nested function `%s' declared `extern'", name);
+ error ("nested function %qs declared %<extern%>", name);
else if (toplevel_bindings_p ())
{
- if (RIDBIT_SETP (RID_AUTO, specbits))
- error ("top-level declaration of `%s' specifies `auto'", name);
+ if (storage_class == sc_auto)
+ error ("top-level declaration of %qs specifies %<auto%>", name);
}
- else if (RIDBIT_SETP (RID_THREAD, specbits)
- && !RIDBIT_SETP (RID_EXTERN, specbits)
- && !RIDBIT_SETP (RID_STATIC, specbits))
+ else if (thread_p
+ && storage_class != sc_extern
+ && storage_class != sc_static)
{
- error ("function-scope `%s' implicitly auto and declared `__thread'",
+ error ("function-scope %qs implicitly auto and declared %<__thread%>",
name);
- RIDBIT_RESET (RID_THREAD, specbits);
+ thread_p = false;
}
- if (nclasses > 0 && friendp)
+ if (storage_class && friendp)
error ("storage class specifiers invalid in friend function declarations");
- scope = get_scope_of_declarator (declarator);
-
- /* Now figure out the structure of the declarator proper.
- Descend through it, creating more complex types, until we reach
- the declared identifier (or NULL_TREE, in an abstract declarator). */
-
- while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
- && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
+ if (!id_declarator)
+ unqualified_id = NULL_TREE;
+ else
{
- /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
- an INDIRECT_REF (for *...),
- a CALL_EXPR (for ...(...)),
- an identifier (for the name being declared)
- or a null pointer (for the place in an absolute declarator
- where the name was omitted).
- For the last two cases, we have just exited the loop.
+ unqualified_id = id_declarator->u.id.unqualified_name;
+ switch (TREE_CODE (unqualified_id))
+ {
+ case BIT_NOT_EXPR:
+ unqualified_id
+ = constructor_name (TREE_OPERAND (unqualified_id, 0));
+ break;
+
+ case IDENTIFIER_NODE:
+ case TEMPLATE_ID_EXPR:
+ break;
- For C++ it could also be
- a SCOPE_REF (for class :: ...). In this case, we have converted
- sensible names to types, and those are the values we use to
- qualify the member name.
- an ADDR_EXPR (for &...),
- a BIT_NOT_EXPR (for destructors)
+ default:
+ gcc_unreachable ();
+ }
+ }
- At this point, TYPE is the type of elements of an array,
- or for a function to return, or for a pointer to point to.
- After this sequence of ifs, TYPE is the type of the
- array or function or pointer, and DECLARATOR has had its
- outermost layer removed. */
+ /* Determine the type of the entity declared by recurring on the
+ declarator. */
+ for (; declarator; declarator = declarator->declarator)
+ {
+ const cp_declarator *inner_declarator;
+ tree attrs;
if (type == error_mark_node)
- {
- if (declarator == error_mark_node)
- return error_mark_node;
- else if (TREE_CODE (declarator) == SCOPE_REF)
- declarator = TREE_OPERAND (declarator, 1);
- else
- declarator = TREE_OPERAND (declarator, 0);
- continue;
- }
- if (quals != NULL_TREE
- && (declarator == NULL_TREE
- || TREE_CODE (declarator) != SCOPE_REF))
- {
- if (ctype == NULL_TREE && TREE_CODE (type) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (type);
- if (ctype != NULL_TREE)
- {
- tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
- grok_method_quals (ctype, dummy, quals);
- type = TREE_TYPE (dummy);
- quals = NULL_TREE;
- }
- }
+ return error_mark_node;
- switch (TREE_CODE (declarator))
+ attrs = declarator->attributes;
+ if (attrs)
{
- case TREE_LIST:
- {
- /* We encode a declarator with embedded attributes using
- a TREE_LIST. */
- tree attrs = TREE_PURPOSE (declarator);
- tree inner_decl;
- int attr_flags;
-
- declarator = TREE_VALUE (declarator);
- inner_decl = declarator;
- while (inner_decl != NULL_TREE
- && TREE_CODE (inner_decl) == TREE_LIST)
- inner_decl = TREE_VALUE (inner_decl);
- attr_flags = 0;
- if (inner_decl == NULL_TREE
- || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
- attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
- if (TREE_CODE (inner_decl) == CALL_EXPR)
- attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
- if (TREE_CODE (inner_decl) == ARRAY_REF)
- attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
- returned_attrs = decl_attributes (&type,
- chainon (returned_attrs, attrs),
- attr_flags);
- }
- break;
+ int attr_flags;
- case ARRAY_REF:
- {
- tree size = TREE_OPERAND (declarator, 1);
- declarator = TREE_OPERAND (declarator, 0);
+ attr_flags = 0;
+ if (declarator == NULL || declarator->kind == cdk_id)
+ attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+ if (declarator->kind == cdk_function)
+ attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+ if (declarator->kind == cdk_array)
+ attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
+ }
- type = create_array_type_for_decl (dname, type, size);
+ if (declarator->kind == cdk_id)
+ break;
- ctype = NULL_TREE;
- }
+ inner_declarator = declarator->declarator;
+
+ switch (declarator->kind)
+ {
+ case cdk_array:
+ type = create_array_type_for_decl (dname, type,
+ declarator->u.array.bounds);
break;
- case CALL_EXPR:
+ case cdk_function:
{
tree arg_types;
int funcdecl_p;
- tree inner_parms = CALL_DECLARATOR_PARMS (declarator);
- tree inner_decl = TREE_OPERAND (declarator, 0);
/* Declaring a function type.
Make sure we have a valid type for the function to return. */
/* We now know that the TYPE_QUALS don't apply to the
- decl, but to its return type. */
+ decl, but to its return type. */
type_quals = TYPE_UNQUALIFIED;
/* Warn about some types functions can't return. */
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("`%s' declared as function returning a function", name);
+ error ("%qs declared as function returning a function", name);
type = integer_type_node;
}
if (TREE_CODE (type) == ARRAY_TYPE)
{
- error ("`%s' declared as function returning an array", name);
+ error ("%qs declared as function returning an array", name);
type = integer_type_node;
}
- if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
- inner_decl = TREE_OPERAND (inner_decl, 1);
-
- if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR)
- inner_decl = dname;
-
/* Pick up type qualifiers which should be applied to `this'. */
- quals = CALL_DECLARATOR_QUALS (declarator);
+ memfn_quals = declarator->u.function.qualifiers;
/* Pick up the exception specifications. */
- raises = CALL_DECLARATOR_EXCEPTION_SPEC (declarator);
+ raises = declarator->u.function.exception_specification;
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
- funcdecl_p
- = inner_decl
- && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
- || TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR
- || TREE_CODE (inner_decl) == BIT_NOT_EXPR);
+ funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id;
if (ctype == NULL_TREE
&& decl_context == FIELD
@@ -7482,75 +7653,52 @@ grokdeclarator (tree declarator,
&& (friendp == 0 || dname == current_class_name))
ctype = current_class_type;
- if (ctype && sfk == sfk_conversion)
- TYPE_HAS_CONVERSION (ctype) = 1;
- if (ctype && constructor_name_p (dname, ctype))
+ if (ctype && (sfk == sfk_constructor
+ || sfk == sfk_destructor))
{
/* We are within a class's scope. If our declarator name
is the same as the class name, and we are defining
a function, then it is a constructor/destructor, and
therefore returns a void type. */
- if (flags == DTOR_FLAG)
+ /* ISO C++ 12.4/2. A destructor may not be declared
+ const or volatile. A destructor may not be
+ static.
+
+ ISO C++ 12.1. A constructor may not be declared
+ const or volatile. A constructor may not be
+ virtual. A constructor may not be static. */
+ if (staticp == 2)
+ error ((flags == DTOR_FLAG)
+ ? "destructor cannot be static member function"
+ : "constructor cannot be static member function");
+ if (memfn_quals)
{
- /* ISO C++ 12.4/2. A destructor may not be
- declared const or volatile. A destructor may
- not be static. */
- if (staticp == 2)
- error ("destructor cannot be static member function");
- if (quals)
- {
- error ("destructors may not be `%s'",
- IDENTIFIER_POINTER (TREE_VALUE (quals)));
- quals = NULL_TREE;
- }
- if (decl_context == FIELD)
- {
- if (! member_function_or_else (ctype,
- current_class_type,
- flags))
- return void_type_node;
- }
+ error ((flags == DTOR_FLAG)
+ ? "destructors may not be cv-qualified"
+ : "constructors may not be cv-qualified");
+ memfn_quals = TYPE_UNQUALIFIED;
}
- else /* It's a constructor. */
+
+ if (decl_context == FIELD
+ && !member_function_or_else (ctype,
+ current_class_type,
+ flags))
+ return error_mark_node;
+
+ if (flags != DTOR_FLAG)
{
+ /* It's a constructor. */
if (explicitp == 1)
explicitp = 2;
- /* ISO C++ 12.1. A constructor may not be
- declared const or volatile. A constructor may
- not be virtual. A constructor may not be
- static. */
- if (staticp == 2)
- error ("constructor cannot be static member function");
if (virtualp)
{
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
- if (quals)
- {
- error ("constructors may not be `%s'",
- IDENTIFIER_POINTER (TREE_VALUE (quals)));
- quals = NULL_TREE;
- }
- {
- RID_BIT_TYPE tmp_bits;
- memcpy (&tmp_bits, &specbits, sizeof (RID_BIT_TYPE));
- RIDBIT_RESET (RID_INLINE, tmp_bits);
- RIDBIT_RESET (RID_STATIC, tmp_bits);
- if (RIDBIT_ANY_SET (tmp_bits))
- error ("return value type specifier for constructor ignored");
- }
- if (decl_context == FIELD)
- {
- if (! member_function_or_else (ctype,
- current_class_type,
- flags))
- return void_type_node;
- TYPE_HAS_CONSTRUCTOR (ctype) = 1;
- if (sfk != sfk_constructor)
- return NULL_TREE;
- }
+ if (decl_context == FIELD
+ && sfk != sfk_constructor)
+ return error_mark_node;
}
if (decl_context == FIELD)
staticp = 0;
@@ -7558,287 +7706,228 @@ grokdeclarator (tree declarator,
else if (friendp)
{
if (initialized)
- error ("can't initialize friend function `%s'", name);
+ error ("can't initialize friend function %qs", name);
if (virtualp)
{
/* Cannot be both friend and virtual. */
error ("virtual functions cannot be friends");
- RIDBIT_RESET (RID_FRIEND, specbits);
friendp = 0;
}
if (decl_context == NORMAL)
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
- error ("can't define friend function `%s' in a local class definition",
- name);
+ error ("can't define friend function %qs in a local "
+ "class definition",
+ name);
}
- /* Construct the function type and go to the next
- inner layer of declarator. */
-
- declarator = TREE_OPERAND (declarator, 0);
+ arg_types = grokparms (declarator->u.function.parameters,
+ &parms);
- arg_types = grokparms (inner_parms, &parms);
-
- if (declarator && flags == DTOR_FLAG)
+ if (inner_declarator
+ && inner_declarator->kind == cdk_id
+ && inner_declarator->u.id.sfk == sfk_destructor
+ && arg_types != void_list_node)
{
- /* A destructor declared in the body of a class will
- be represented as a BIT_NOT_EXPR. But, we just
- want the underlying IDENTIFIER. */
- if (TREE_CODE (declarator) == BIT_NOT_EXPR)
- declarator = TREE_OPERAND (declarator, 0);
-
- if (arg_types != void_list_node)
- {
- error ("destructors may not have parameters");
- arg_types = void_list_node;
- parms = NULL_TREE;
- }
+ error ("destructors may not have parameters");
+ arg_types = void_list_node;
+ parms = NULL_TREE;
}
- /* ANSI says that `const int foo ();'
- does not make the function foo const. */
type = build_function_type (type, arg_types);
}
break;
- case ADDR_EXPR:
- case INDIRECT_REF:
+ case cdk_pointer:
+ case cdk_reference:
+ case cdk_ptrmem:
/* Filter out pointers-to-references and references-to-references.
We can get these if a TYPE_DECL is used. */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- error (TREE_CODE (declarator) == ADDR_EXPR
- ? "cannot declare reference to `%#T'"
- : "cannot declare pointer to `%#T'", type);
+ error (declarator->kind == cdk_reference
+ ? "cannot declare reference to %q#T"
+ : "cannot declare pointer to %q#T", type);
type = TREE_TYPE (type);
}
- else if (VOID_TYPE_P (type)
- && (ctype || TREE_CODE (declarator) == ADDR_EXPR))
- error (ctype ? "cannot declare pointer to `%#T' member"
- : "cannot declare reference to `%#T'", type);
-
- /* Merge any constancy or volatility into the target type
- for the pointer. */
+ else if (VOID_TYPE_P (type))
+ {
+ if (declarator->kind == cdk_reference)
+ error ("cannot declare reference to %q#T", type);
+ else if (declarator->kind == cdk_ptrmem)
+ error ("cannot declare pointer to %q#T member", type);
+ }
/* We now know that the TYPE_QUALS don't apply to the decl,
but to the target of the pointer. */
type_quals = TYPE_UNQUALIFIED;
- if (TREE_CODE (declarator) == ADDR_EXPR)
+ if (declarator->kind == cdk_ptrmem
+ && (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
+ {
+ memfn_quals |= cp_type_quals (type);
+ type = build_memfn_type (type,
+ declarator->u.pointer.class_type,
+ memfn_quals);
+ memfn_quals = TYPE_UNQUALIFIED;
+ }
+
+ if (declarator->kind == cdk_reference)
{
if (!VOID_TYPE_P (type))
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
- else if (ctype)
- type = build_ptrmem_type (ctype, type);
+ else if (declarator->kind == cdk_ptrmem)
+ {
+ gcc_assert (TREE_CODE (declarator->u.pointer.class_type)
+ != NAMESPACE_DECL);
+ if (declarator->u.pointer.class_type == error_mark_node)
+ /* We will already have complained. */
+ type = error_mark_node;
+ else
+ type = build_ptrmem_type (declarator->u.pointer.class_type,
+ type);
+ }
else
type = build_pointer_type (type);
/* Process a list of type modifier keywords (such as
const or volatile) that were given inside the `*' or `&'. */
- if (TREE_TYPE (declarator))
+ if (declarator->u.pointer.qualifiers)
{
- tree typemodlist;
- int erred = 0;
- int constp = 0;
- int volatilep = 0;
- int restrictp = 0;
-
- for (typemodlist = TREE_TYPE (declarator); typemodlist;
- typemodlist = TREE_CHAIN (typemodlist))
- {
- tree qualifier = TREE_VALUE (typemodlist);
-
- if (qualifier == ridpointers[(int) RID_CONST])
- {
- constp++;
- type_quals |= TYPE_QUAL_CONST;
- }
- else if (qualifier == ridpointers[(int) RID_VOLATILE])
- {
- volatilep++;
- type_quals |= TYPE_QUAL_VOLATILE;
- }
- else if (qualifier == ridpointers[(int) RID_RESTRICT])
- {
- restrictp++;
- type_quals |= TYPE_QUAL_RESTRICT;
- }
- else if (!erred)
- {
- erred = 1;
- error ("invalid type modifier within pointer declarator");
- }
- }
- if (constp > 1)
- pedwarn ("duplicate `const'");
- if (volatilep > 1)
- pedwarn ("duplicate `volatile'");
- if (restrictp > 1)
- pedwarn ("duplicate `restrict'");
- type = cp_build_qualified_type (type, type_quals);
+ type
+ = cp_build_qualified_type (type,
+ declarator->u.pointer.qualifiers);
type_quals = cp_type_quals (type);
}
- declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
break;
- case SCOPE_REF:
- {
- /* We have converted type names to NULL_TREE if the
- name was bogus, or to a _TYPE node, if not.
-
- The variable CTYPE holds the type we will ultimately
- resolve to. The code here just needs to build
- up appropriate member types. */
- tree sname = TREE_OPERAND (declarator, 1);
- tree t;
-
- /* Destructors can have their visibilities changed as well. */
- if (TREE_CODE (sname) == BIT_NOT_EXPR)
- sname = TREE_OPERAND (sname, 0);
-
- if (TREE_OPERAND (declarator, 0) == NULL_TREE)
- {
- /* We had a reference to a global decl, or
- perhaps we were given a non-aggregate typedef,
- in which case we cleared this out, and should just
- keep going as though it wasn't there. */
- declarator = sname;
- continue;
- }
- ctype = TREE_OPERAND (declarator, 0);
-
- t = ctype;
- if (TREE_CODE (TREE_OPERAND (declarator, 1)) != INDIRECT_REF)
- while (t != NULL_TREE && CLASS_TYPE_P (t))
- {
- /* You're supposed to have one `template <...>'
- for every template class, but you don't need one
- for a full specialization. For example:
-
- template <class T> struct S{};
- template <> struct S<int> { void f(); };
- void S<int>::f () {}
-
- is correct; there shouldn't be a `template <>' for
- the definition of `S<int>::f'. */
- if (CLASSTYPE_TEMPLATE_INFO (t)
- && (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
- || uses_template_parms (CLASSTYPE_TI_ARGS (t)))
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
- template_count += 1;
-
- t = TYPE_MAIN_DECL (t);
- t = DECL_CONTEXT (t);
- }
-
- if (sname == NULL_TREE)
- goto done_scoping;
-
- if (TREE_CODE (sname) == IDENTIFIER_NODE)
- {
- /* This is the `standard' use of the scoping operator:
- basetype :: member . */
-
- if (ctype == current_class_type)
- {
- /* class A {
- void A::f ();
- };
-
- Is this ill-formed? */
-
- if (pedantic)
- pedwarn ("extra qualification `%T::' on member `%s' ignored",
- ctype, name);
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- if (NEW_DELETE_OPNAME_P (sname))
- /* Overloaded operator new and operator delete
- are always static functions. */
- ;
- else if (current_class_type == NULL_TREE || friendp)
- type
- = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- else
- {
- error ("cannot declare member function `%T::%s' within `%T'",
- ctype, name, current_class_type);
- return error_mark_node;
- }
- }
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
- || COMPLETE_TYPE_P (complete_type (ctype)))
- {
- /* Have to move this code elsewhere in this function.
- this code is used for i.e., typedef int A::M; M *pm;
-
- It is? How? jason 10/2/94 */
+ case cdk_error:
+ break;
- if (current_class_type)
- {
- error ("cannot declare member `%T::%s' within `%T'",
- ctype, name, current_class_type);
- return void_type_node;
- }
- }
- else
- {
- cxx_incomplete_type_error (NULL_TREE, ctype);
- return error_mark_node;
- }
+ default:
+ gcc_unreachable ();
+ }
+ }
- declarator = sname;
- }
- else if (TREE_CODE (sname) == SCOPE_REF)
- abort ();
- else
- {
- done_scoping:
- declarator = TREE_OPERAND (declarator, 1);
- if (declarator && TREE_CODE (declarator) == CALL_EXPR)
- /* In this case, we will deal with it later. */
- ;
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- }
- }
- break;
+ if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
+ && TREE_CODE (type) != FUNCTION_TYPE
+ && TREE_CODE (type) != METHOD_TYPE)
+ {
+ error ("template-id %qD used as a declarator",
+ unqualified_id);
+ unqualified_id = dname;
+ }
- case BIT_NOT_EXPR:
- declarator = TREE_OPERAND (declarator, 0);
- break;
+ /* If TYPE is a FUNCTION_TYPE, but the function name was explicitly
+ qualified with a class-name, turn it into a METHOD_TYPE, unless
+ we know that the function is static. We take advantage of this
+ opportunity to do other processing that pertains to entities
+ explicitly declared to be class members. Note that if DECLARATOR
+ is non-NULL, we know it is a cdk_id declarator; otherwise, we
+ would not have exited the loop above. */
+ if (declarator
+ && declarator->u.id.qualifying_scope
+ && TYPE_P (declarator->u.id.qualifying_scope))
+ {
+ tree t;
+
+ ctype = declarator->u.id.qualifying_scope;
+ ctype = TYPE_MAIN_VARIANT (ctype);
+ t = ctype;
+ while (t != NULL_TREE && CLASS_TYPE_P (t))
+ {
+ /* You're supposed to have one `template <...>' for every
+ template class, but you don't need one for a full
+ specialization. For example:
+
+ template <class T> struct S{};
+ template <> struct S<int> { void f(); };
+ void S<int>::f () {}
+
+ is correct; there shouldn't be a `template <>' for the
+ definition of `S<int>::f'. */
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
+ && !any_dependent_template_arguments_p (CLASSTYPE_TI_ARGS (t)))
+ /* T is an explicit (not partial) specialization. All
+ containing classes must therefore also be explicitly
+ specialized. */
+ break;
+ if ((CLASSTYPE_USE_TEMPLATE (t) || CLASSTYPE_IS_TEMPLATE (t))
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+ template_count += 1;
- case BASELINK:
- declarator = BASELINK_FUNCTIONS (declarator);
- break;
+ t = TYPE_MAIN_DECL (t);
+ t = DECL_CONTEXT (t);
+ }
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- declarator = NULL_TREE;
- break;
+ if (ctype == current_class_type)
+ {
+ if (friendp)
+ pedwarn ("member functions are implicitly friends of their class");
+ else
+ pedwarn ("extra qualification %<%T::%> on member %qs",
+ ctype, name);
+ }
+ else if (/* If the qualifying type is already complete, then we
+ can skip the following checks. */
+ !COMPLETE_TYPE_P (ctype)
+ && (/* If the function is being defined, then
+ qualifying type must certainly be complete. */
+ funcdef_flag
+ /* A friend declaration of "T::f" is OK, even if
+ "T" is a template parameter. But, if this
+ function is not a friend, the qualifying type
+ must be a class. */
+ || (!friendp && !CLASS_TYPE_P (ctype))
+ /* For a declaration, the type need not be
+ complete, if either it is dependent (since there
+ is no meaningful definition of complete in that
+ case) or the qualifying class is currently being
+ defined. */
+ || !(dependent_type_p (ctype)
+ || currently_open_class (ctype)))
+ /* Check that the qualifying type is complete. */
+ && !complete_type_or_else (ctype, NULL_TREE))
+ return error_mark_node;
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ tree sname = declarator->u.id.unqualified_name;
- case ERROR_MARK:
- declarator = NULL_TREE;
- break;
+ if (current_class_type
+ && (!friendp || funcdef_flag))
+ {
+ error (funcdef_flag
+ ? "cannot define member function %<%T::%s%> within %<%T%>"
+ : "cannot declare member function %<%T::%s%> within %<%T%>",
+ ctype, name, current_class_type);
+ return error_mark_node;
+ }
- default:
- abort ();
+ if (TREE_CODE (sname) == IDENTIFIER_NODE
+ && NEW_DELETE_OPNAME_P (sname))
+ /* Overloaded operator new and operator delete
+ are always static functions. */
+ ;
+ else
+ type = build_memfn_type (type, ctype, memfn_quals);
+ }
+ else if (declspecs->specs[(int)ds_typedef]
+ && current_class_type)
+ {
+ error ("cannot declare member %<%T::%s%> within %qT",
+ ctype, name, current_class_type);
+ return error_mark_node;
}
}
+ /* Now TYPE has the actual type. */
+
if (returned_attrs)
{
if (attrlist)
@@ -7847,87 +7936,70 @@ grokdeclarator (tree declarator,
attrlist = &returned_attrs;
}
- /* Now TYPE has the actual type. */
-
/* Did array size calculations overflow? */
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
- && TREE_OVERFLOW (TYPE_SIZE (type)))
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
+ && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
{
- error ("size of array `%s' is too large", name);
+ error ("size of array %qs is too large", name);
/* If we proceed with the array type as it is, we'll eventually
crash in tree_low_cst(). */
type = error_mark_node;
}
if ((decl_context == FIELD || decl_context == PARM)
- && !processing_template_decl
- && variably_modified_type_p (type))
+ && !processing_template_decl
+ && variably_modified_type_p (type, NULL_TREE))
{
if (decl_context == FIELD)
- error ("data member may not have variably modified type `%T'", type);
+ error ("data member may not have variably modified type %qT", type);
else
- error ("parameter may not have variably modified type `%T'", type);
+ error ("parameter may not have variably modified type %qT", type);
type = error_mark_node;
}
if (explicitp == 1 || (explicitp && friendp))
{
/* [dcl.fct.spec] The explicit specifier shall only be used in
- declarations of constructors within a class definition. */
- error ("only declarations of constructors can be `explicit'");
+ declarations of constructors within a class definition. */
+ error ("only declarations of constructors can be %<explicit%>");
explicitp = 0;
}
- if (RIDBIT_SETP (RID_MUTABLE, specbits))
+ if (storage_class == sc_mutable)
{
if (decl_context != FIELD || friendp)
- {
- error ("non-member `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
- }
- else if (decl_context == TYPENAME || RIDBIT_SETP (RID_TYPEDEF, specbits))
{
- error ("non-object member `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ error ("non-member %qs cannot be declared %<mutable%>", name);
+ storage_class = sc_none;
+ }
+ else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
+ {
+ error ("non-object member %qs cannot be declared %<mutable%>", name);
+ storage_class = sc_none;
}
else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
- {
- error ("function `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
- }
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ error ("function %qs cannot be declared %<mutable%>", name);
+ storage_class = sc_none;
+ }
else if (staticp)
{
- error ("static `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ error ("static %qs cannot be declared %<mutable%>", name);
+ storage_class = sc_none;
}
else if (type_quals & TYPE_QUAL_CONST)
{
- error ("const `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ error ("const %qs cannot be declared %<mutable%>", name);
+ storage_class = sc_none;
}
}
- if (declarator == NULL_TREE
- || TREE_CODE (declarator) == IDENTIFIER_NODE
- || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
- && (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)))
- /* OK */;
- else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
- {
- error ("template-id `%D' used as a declarator", declarator);
- declarator = dname;
- }
- else
- /* Unexpected declarator format. */
- abort ();
-
/* If this is declaring a typedef name, return a TYPE_DECL. */
-
- if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
+ if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME)
{
tree decl;
@@ -7936,28 +8008,49 @@ grokdeclarator (tree declarator,
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
+ /* This declaration:
+
+ typedef void f(int) const;
+
+ declares a function type which is not a member of any
+ particular class, but which is cv-qualified; for
+ example "f S::*" declares a pointer to a const-qualified
+ member function of S. We record the cv-qualification in the
+ function type. */
+ if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
+ type = cp_build_qualified_type (type, memfn_quals);
+
if (decl_context == FIELD)
- {
- if (constructor_name_p (declarator, current_class_type))
- pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
- declarator);
- decl = build_lang_decl (TYPE_DECL, declarator, type);
- }
+ decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
+ decl = build_decl (TYPE_DECL, unqualified_id, type);
+ if (id_declarator && declarator->u.id.qualifying_scope)
+ error ("%Jtypedef name may not be a nested-name-specifier", decl);
+
+ if (decl_context != FIELD)
{
- decl = build_decl (TYPE_DECL, declarator, type);
- if (in_namespace || ctype)
- error ("%Jtypedef name may not be a nested-name-specifier", decl);
if (!current_function_decl)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
- }
-
+ else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl)
+ || (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P
+ (current_function_decl)))
+ /* The TYPE_DECL is "abstract" because there will be
+ clones of this constructor/destructor, and there will
+ be copies of this TYPE_DECL generated in those
+ clones. */
+ DECL_ABSTRACT (decl) = 1;
+ }
+ else if (constructor_name_p (unqualified_id, current_class_type))
+ pedwarn ("ISO C++ forbids nested type %qD with same name "
+ "as enclosing class",
+ unqualified_id);
+
/* If the user declares "typedef struct {...} foo" then the
struct will have an anonymous name. Fill that name in now.
Nothing can refer to it, so nothing needs know about the name
change. */
if (type != error_mark_node
- && declarator
+ && unqualified_id
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_ANONYMOUS_P (type)
@@ -7969,7 +8062,6 @@ grokdeclarator (tree declarator,
tree t;
/* Replace the anonymous name with the real name everywhere. */
- lookup_tag_reverse (type, declarator);
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (TYPE_NAME (t) == oldname)
TYPE_NAME (t) = decl;
@@ -7988,25 +8080,17 @@ grokdeclarator (tree declarator,
type with external linkage have external linkage. */
}
- if (quals)
- {
- if (ctype == NULL_TREE)
- {
- if (TREE_CODE (type) != METHOD_TYPE)
- error ("%Jinvalid type qualifier for non-member function type",
- decl);
- else
- ctype = TYPE_METHOD_BASETYPE (type);
- }
- if (ctype != NULL_TREE)
- grok_method_quals (ctype, decl, quals);
- }
+ /* Any qualifiers on a function type typedef have already been
+ dealt with. */
+ if (memfn_quals && !ctype && TREE_CODE (type) == FUNCTION_TYPE)
+ memfn_quals = TYPE_UNQUALIFIED;
- if (RIDBIT_SETP (RID_SIGNED, specbits)
+ if (signed_p
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
+ bad_specifiers (decl, "type", virtualp,
+ memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
return decl;
@@ -8024,7 +8108,7 @@ grokdeclarator (tree declarator,
/* Detect where we're using a typedef of function type to declare a
function. PARMS will not be set, so we must create it now. */
-
+
if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
{
tree decls = NULL_TREE;
@@ -8037,8 +8121,25 @@ grokdeclarator (tree declarator,
TREE_CHAIN (decl) = decls;
decls = decl;
}
-
+
parms = nreverse (decls);
+
+ if (decl_context != TYPENAME)
+ {
+ /* A cv-qualifier-seq shall only be part of the function type
+ for a non-static member function. [8.3.5/4 dcl.fct] */
+ if (cp_type_quals (type) != TYPE_UNQUALIFIED
+ && (current_class_type == NULL_TREE || staticp) )
+ {
+ error ("qualified function types cannot be used to declare %s functions",
+ (staticp? "static member" : "free"));
+ type = TYPE_MAIN_VARIANT (type);
+ }
+
+ /* The qualifiers on the function type become the qualifiers on
+ the non-static member function. */
+ memfn_quals |= cp_type_quals (type);
+ }
}
/* If this is a type name (such as, in a cast or sizeof),
@@ -8061,7 +8162,7 @@ grokdeclarator (tree declarator,
}
if (inlinep)
{
- error ("`inline' specified for friend class declaration");
+ error ("%<inline%> specified for friend class declaration");
inlinep = 0;
}
@@ -8071,12 +8172,12 @@ grokdeclarator (tree declarator,
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
pedwarn ("template parameters cannot be friends");
else if (TREE_CODE (type) == TYPENAME_TYPE)
- pedwarn ("friend declaration requires class-key, "
- "i.e. `friend class %T::%D'",
+ pedwarn ("friend declaration requires class-key, "
+ "i.e. %<friend class %T::%D%>",
TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
else
- pedwarn ("friend declaration requires class-key, "
- "i.e. `friend %#T'",
+ pedwarn ("friend declaration requires class-key, "
+ "i.e. %<friend %#T%>",
type);
}
@@ -8088,55 +8189,54 @@ grokdeclarator (tree declarator,
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type),
/*complain=*/true);
else
- error ("trying to make class `%T' a friend of global scope",
- type);
+ error ("trying to make class %qT a friend of global scope",
+ type);
type = void_type_node;
}
}
- else if (quals)
+ else if (memfn_quals)
{
if (ctype == NULL_TREE)
{
if (TREE_CODE (type) != METHOD_TYPE)
- error ("invalid qualifiers on non-member function type");
+ error ("invalid qualifiers on non-member function type");
else
- ctype = TYPE_METHOD_BASETYPE (type);
+ ctype = TYPE_METHOD_BASETYPE (type);
}
if (ctype)
- {
- tree dummy = build_decl (TYPE_DECL, declarator, type);
- grok_method_quals (ctype, dummy, quals);
- type = TREE_TYPE (dummy);
- }
+ type = build_memfn_type (type, ctype, memfn_quals);
}
return type;
}
- else if (declarator == NULL_TREE && decl_context != PARM
+ else if (unqualified_id == NULL_TREE && decl_context != PARM
&& decl_context != CATCHPARM
&& TREE_CODE (type) != UNION_TYPE
&& ! bitfield)
{
- error ("abstract declarator `%T' used as declaration", type);
+ error ("abstract declarator %qT used as declaration", type);
return error_mark_node;
}
/* Only functions may be declared using an operator-function-id. */
- if (declarator
- && TREE_CODE (declarator) == IDENTIFIER_NODE
- && IDENTIFIER_OPNAME_P (declarator)
+ if (unqualified_id
+ && IDENTIFIER_OPNAME_P (unqualified_id)
&& TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE)
{
- error ("declaration of `%D' as non-function", declarator);
+ error ("declaration of %qD as non-function", unqualified_id);
return error_mark_node;
}
/* We don't check parameter types here because we can emit a better
error message later. */
if (decl_context != PARM)
- type = check_var_type (declarator, type);
+ {
+ type = check_var_type (unqualified_id, type);
+ if (type == error_mark_node)
+ return error_mark_node;
+ }
/* Now create the decl, which may be a VAR_DECL, a PARM_DECL
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
@@ -8144,7 +8244,7 @@ grokdeclarator (tree declarator,
if (decl_context == PARM || decl_context == CATCHPARM)
{
if (ctype || in_namespace)
- error ("cannot use `::' in parameter declaration");
+ error ("cannot use %<::%> in parameter declaration");
/* A parameter declared as an array of T is really a pointer to T.
One declared as a function is really a pointer to a function.
@@ -8165,9 +8265,10 @@ grokdeclarator (tree declarator,
if (decl_context == PARM)
{
- decl = cp_build_parm_decl (declarator, type);
+ decl = cp_build_parm_decl (unqualified_id, type);
- bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
+ bad_specifiers (decl, "parameter", virtualp,
+ memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
else if (decl_context == FIELD)
@@ -8189,23 +8290,14 @@ grokdeclarator (tree declarator,
else if (in_namespace && !friendp)
{
/* Something like struct S { int N::j; }; */
- error ("invalid use of `::'");
- decl = NULL_TREE;
+ error ("invalid use of %<::%>");
+ return error_mark_node;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
int publicp = 0;
tree function_context;
- /* We catch the others as conflicts with the builtin
- typedefs. */
- if (friendp && declarator == ridpointers[(int) RID_SIGNED])
- {
- error ("function `%D' cannot be declared friend",
- declarator);
- friendp = 0;
- }
-
if (friendp == 0)
{
if (ctype == NULL_TREE)
@@ -8213,33 +8305,54 @@ grokdeclarator (tree declarator,
if (ctype == NULL_TREE)
{
- error ("can't make `%D' into a method -- not in a class",
- declarator);
- return void_type_node;
+ error ("can't make %qD into a method -- not in a class",
+ unqualified_id);
+ return error_mark_node;
}
/* ``A union may [ ... ] not [ have ] virtual functions.''
ARM 9.5 */
if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
{
- error ("function `%D' declared virtual inside a union",
- declarator);
- return void_type_node;
+ error ("function %qD declared virtual inside a union",
+ unqualified_id);
+ return error_mark_node;
}
- if (NEW_DELETE_OPNAME_P (declarator))
+ if (NEW_DELETE_OPNAME_P (unqualified_id))
{
if (virtualp)
{
- error ("`%D' cannot be declared virtual, since it is always static",
- declarator);
+ error ("%qD cannot be declared virtual, since it "
+ "is always static",
+ unqualified_id);
virtualp = 0;
}
}
else if (staticp < 2)
- type = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
+ type = build_memfn_type (type, ctype, memfn_quals);
+ }
+
+ /* Check that the name used for a destructor makes sense. */
+ if (sfk == sfk_destructor)
+ {
+ if (!ctype)
+ {
+ gcc_assert (friendp);
+ error ("expected qualified name in friend declaration "
+ "for destructor %qD",
+ id_declarator->u.id.unqualified_name);
+ return error_mark_node;
+ }
+
+ if (!same_type_p (TREE_OPERAND
+ (id_declarator->u.id.unqualified_name, 0),
+ ctype))
+ {
+ error ("declaration of %qD as member of %qT",
+ id_declarator->u.id.unqualified_name, ctype);
+ return error_mark_node;
+ }
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
@@ -8248,15 +8361,16 @@ grokdeclarator (tree declarator,
publicp = (! friendp || ! staticp)
&& function_context == NULL_TREE;
decl = grokfndecl (ctype, type,
- TREE_CODE (declarator) != TEMPLATE_ID_EXPR
- ? declarator : dname,
+ TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
+ ? unqualified_id : dname,
parms,
- declarator,
- virtualp, flags, quals, raises,
+ unqualified_id,
+ virtualp, flags, memfn_quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
- funcdef_flag, template_count, in_namespace);
+ sfk,
+ funcdef_flag, template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
- return decl;
+ return error_mark_node;
#if 0
/* This clobbers the attrs stored in `decl' from `attrlist'. */
/* The decl and setting of decl_attr is also turned off. */
@@ -8295,44 +8409,44 @@ grokdeclarator (tree declarator,
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type,
- TREE_CODE (declarator) != TEMPLATE_ID_EXPR
- ? declarator : dname,
+ TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
+ ? unqualified_id : dname,
parms,
- declarator,
- virtualp, flags, quals, raises,
- friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
- template_count, in_namespace);
+ unqualified_id,
+ virtualp, flags, memfn_quals, raises,
+ friendp ? -1 : 0, friendp, 1, 0, sfk,
+ funcdef_flag, template_count, in_namespace,
+ attrlist);
if (decl == NULL_TREE)
- return NULL_TREE;
+ return error_mark_node;
}
else if (!staticp && !dependent_type_p (type)
&& !COMPLETE_TYPE_P (complete_type (type))
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
- if (declarator)
- error ("field `%D' has incomplete type", declarator);
+ if (unqualified_id)
+ error ("field %qD has incomplete type", unqualified_id);
else
- error ("name `%T' has incomplete type", type);
+ error ("name %qT has incomplete type", type);
/* If we're instantiating a template, tell them which
instantiation made the field's type be incomplete. */
if (current_class_type
&& TYPE_NAME (current_class_type)
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
- && declspecs && TREE_VALUE (declspecs)
- && TREE_TYPE (TREE_VALUE (declspecs)) == type)
- error (" in instantiation of template `%T'",
- current_class_type);
+ && declspecs->type
+ && declspecs->type == type)
+ error (" in instantiation of template %qT",
+ current_class_type);
- type = error_mark_node;
- decl = NULL_TREE;
+ return error_mark_node;
}
else
{
if (friendp)
{
- error ("`%s' is neither function nor member function; cannot be declared friend",
- IDENTIFIER_POINTER (declarator));
+ error ("%qE is neither function nor member function; "
+ "cannot be declared friend", unqualified_id);
friendp = 0;
}
decl = NULL_TREE;
@@ -8342,24 +8456,25 @@ grokdeclarator (tree declarator,
{
/* Friends are treated specially. */
if (ctype == current_class_type)
- warning ("member functions are implicitly friends of their class");
- else if (decl && DECL_NAME (decl))
+ ; /* We already issued a pedwarn. */
+ else if (decl && DECL_NAME (decl))
{
if (template_class_depth (current_class_type) == 0)
{
decl = check_explicit_specialization
- (declarator, decl, template_count,
- 2 * (funcdef_flag != 0) + 4);
+ (unqualified_id, decl, template_count,
+ 2 * funcdef_flag + 4);
if (decl == error_mark_node)
return error_mark_node;
}
-
- decl = do_friend (ctype, declarator, decl,
- *attrlist, flags, quals, funcdef_flag);
+
+ decl = do_friend (ctype, unqualified_id, decl,
+ *attrlist, flags,
+ funcdef_flag);
return decl;
}
else
- return void_type_node;
+ return error_mark_node;
}
/* Structure field. It may not be a function, except for C++. */
@@ -8382,46 +8497,60 @@ grokdeclarator (tree declarator,
the rest of the compiler does not correctly
handle the initialization unless the member is
static so we make it static below. */
- pedwarn ("ISO C++ forbids initialization of member `%D'",
- declarator);
- pedwarn ("making `%D' static", declarator);
+ pedwarn ("ISO C++ forbids initialization of member %qD",
+ unqualified_id);
+ pedwarn ("making %qD static", unqualified_id);
staticp = 1;
}
if (uses_template_parms (type))
/* We'll check at instantiation time. */
;
- else if (check_static_variable_definition (declarator,
+ else if (check_static_variable_definition (unqualified_id,
type))
/* If we just return the declaration, crashes
will sometimes occur. We therefore return
void_type_node, as if this was a friend
declaration, to cause callers to completely
ignore this declaration. */
- return void_type_node;
+ return error_mark_node;
}
if (staticp)
{
/* C++ allows static class members. All other work
for this is done by grokfield. */
- decl = build_lang_decl (VAR_DECL, declarator, type);
- TREE_STATIC (decl) = 1;
- /* In class context, 'static' means public access. */
- TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
+ decl = build_lang_decl (VAR_DECL, unqualified_id, type);
+ set_linkage_for_static_data_member (decl);
+ /* Even if there is an in-class initialization, DECL
+ is considered undefined until an out-of-class
+ definition is provided. */
+ DECL_EXTERNAL (decl) = 1;
+
+ if (thread_p)
+ {
+ if (targetm.have_tls)
+ DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
+ else
+ /* A mere warning is sure to result in improper
+ semantics at runtime. Don't bother to allow this to
+ compile. */
+ error ("thread-local storage not supported for this target");
+ }
}
else
{
- decl = build_decl (FIELD_DECL, declarator, type);
+ decl = build_decl (FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
- if (RIDBIT_SETP (RID_MUTABLE, specbits))
+ if (storage_class == sc_mutable)
{
DECL_MUTABLE_P (decl) = 1;
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ storage_class = sc_none;
}
}
- bad_specifiers (decl, "field", virtualp, quals != NULL_TREE,
+ bad_specifiers (decl, "field", virtualp,
+ memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
}
@@ -8431,61 +8560,63 @@ grokdeclarator (tree declarator,
tree original_name;
int publicp = 0;
- if (! declarator)
- return NULL_TREE;
+ if (!unqualified_id)
+ return error_mark_node;
- if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
original_name = dname;
else
- original_name = declarator;
+ original_name = unqualified_id;
- if (RIDBIT_SETP (RID_AUTO, specbits))
- error ("storage class `auto' invalid for function `%s'", name);
- else if (RIDBIT_SETP (RID_REGISTER, specbits))
- error ("storage class `register' invalid for function `%s'", name);
- else if (RIDBIT_SETP (RID_THREAD, specbits))
- error ("storage class `__thread' invalid for function `%s'", name);
+ if (storage_class == sc_auto)
+ error ("storage class %<auto%> invalid for function %qs", name);
+ else if (storage_class == sc_register)
+ error ("storage class %<register%> invalid for function %qs", name);
+ else if (thread_p)
+ error ("storage class %<__thread%> invalid for function %qs", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
if (! toplevel_bindings_p ()
- && (RIDBIT_SETP (RID_STATIC, specbits)
- || RIDBIT_SETP (RID_INLINE, specbits))
+ && (storage_class == sc_static
+ || declspecs->specs[(int)ds_inline])
&& pedantic)
{
- if (RIDBIT_SETP (RID_STATIC, specbits))
- pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name);
+ if (storage_class == sc_static)
+ pedwarn ("%<static%> specified invalid for function %qs "
+ "declared out of global scope", name);
else
- pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name);
+ pedwarn ("%<inline%> specifier invalid for function %qs "
+ "declared out of global scope", name);
}
if (ctype == NULL_TREE)
{
if (virtualp)
{
- error ("virtual non-class function `%s'", name);
+ error ("virtual non-class function %qs", name);
virtualp = 0;
}
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
&& !NEW_DELETE_OPNAME_P (original_name))
- type = build_method_type_directly (ctype,
+ type = build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
- || RIDBIT_SETP (RID_EXTERN, specbits)
- || !RIDBIT_SETP (RID_STATIC, specbits));
+ || storage_class == sc_extern
+ || storage_class != sc_static);
- decl = grokfndecl (ctype, type, original_name, parms, declarator,
- virtualp, flags, quals, raises,
+ decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
+ virtualp, flags, memfn_quals, raises,
1, friendp,
- publicp, inlinep, funcdef_flag,
- template_count, in_namespace);
+ publicp, inlinep, sfk, funcdef_flag,
+ template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
- return NULL_TREE;
+ return error_mark_node;
if (staticp == 1)
{
@@ -8495,7 +8626,8 @@ grokdeclarator (tree declarator,
declaring main to be static. */
if (TREE_CODE (type) == METHOD_TYPE)
{
- pedwarn ("cannot declare member function `%D' to have static linkage", decl);
+ pedwarn ("cannot declare member function %qD to have "
+ "static linkage", decl);
invalid_static = 1;
}
else if (current_function_decl)
@@ -8508,7 +8640,7 @@ grokdeclarator (tree declarator,
if (invalid_static)
{
staticp = 0;
- RIDBIT_RESET (RID_STATIC, specbits);
+ storage_class = sc_none;
}
}
}
@@ -8517,11 +8649,13 @@ grokdeclarator (tree declarator,
/* It's a variable. */
/* An uninitialized decl with `extern' is a reference. */
- decl = grokvardecl (type, declarator, &specbits,
+ decl = grokvardecl (type, unqualified_id,
+ declspecs,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
- bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
+ bad_specifiers (decl, "variable", virtualp,
+ memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
if (ctype)
@@ -8529,43 +8663,41 @@ grokdeclarator (tree declarator,
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
- pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
- staticp = 0;
- RIDBIT_RESET (RID_STATIC, specbits);
+ pedwarn ("%<static%> may not be used when defining "
+ "(as opposed to declaring) a static data member");
+ staticp = 0;
+ storage_class = sc_none;
}
- if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
+ if (storage_class == sc_register && TREE_STATIC (decl))
{
- error ("static member `%D' declared `register'", decl);
- RIDBIT_RESET (RID_REGISTER, specbits);
+ error ("static member %qD declared %<register%>", decl);
+ storage_class = sc_none;
}
- if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic)
+ if (storage_class == sc_extern && pedantic)
{
- pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
- decl);
- RIDBIT_RESET (RID_EXTERN, specbits);
+ pedwarn ("cannot explicitly declare member %q#D to have "
+ "extern linkage",
+ decl);
+ storage_class = sc_none;
}
}
}
- my_friendly_assert (!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927);
-
/* Record `register' declaration for warnings on &
and in case doing stupid register allocation. */
- if (RIDBIT_SETP (RID_REGISTER, specbits))
+ if (storage_class == sc_register)
DECL_REGISTER (decl) = 1;
-
- if (RIDBIT_SETP (RID_EXTERN, specbits))
+ else if (storage_class == sc_extern)
DECL_THIS_EXTERN (decl) = 1;
-
- if (RIDBIT_SETP (RID_STATIC, specbits))
+ else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. There's no need to do this
when processing a template; we'll do this for the instantiated
declaration based on the type of DECL. */
if (!processing_template_decl)
- c_apply_type_quals_to_decl (type_quals, decl);
+ cp_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
@@ -8580,14 +8712,18 @@ require_complete_types_for_parms (tree parms)
{
for (; parms; parms = TREE_CHAIN (parms))
{
- if (VOID_TYPE_P (TREE_TYPE (parms)))
- /* grokparms will have already issued an error. */
- TREE_TYPE (parms) = error_mark_node;
- else if (complete_type_or_else (TREE_TYPE (parms), parms))
+ if (dependent_type_p (TREE_TYPE (parms)))
+ continue;
+ if (!VOID_TYPE_P (TREE_TYPE (parms))
+ && complete_type_or_else (TREE_TYPE (parms), parms))
{
- layout_decl (parms, 0);
+ relayout_decl (parms);
DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
}
+ else
+ /* grokparms or complete_type_or_else will have already issued
+ an error. */
+ TREE_TYPE (parms) = error_mark_node;
}
}
@@ -8624,14 +8760,18 @@ nonstatic_local_decl_p (tree t)
function. */
static tree
-local_variable_p_walkfn (tree* tp,
- int* walk_subtrees ATTRIBUTE_UNUSED ,
- void* data ATTRIBUTE_UNUSED )
+local_variable_p_walkfn (tree *tp, int *walk_subtrees,
+ void *data ATTRIBUTE_UNUSED)
{
- return ((local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
- ? *tp : NULL_TREE);
+ if (local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
+ return *tp;
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+
+ return NULL_TREE;
}
+
/* Check that ARG, which is a default-argument expression for a
parameter DECL, is valid. Returns ARG, or ERROR_MARK_NODE, if
something goes wrong. DECL may also be a _TYPE node, rather than a
@@ -8649,13 +8789,6 @@ check_default_argument (tree decl, tree arg)
deal with it after the class is complete. */
return arg;
- if (processing_template_decl || uses_template_parms (arg))
- /* We don't do anything checking until instantiation-time. Note
- that there may be uninstantiated arguments even for an
- instantiated function, since default arguments are not
- instantiated until they are needed. */
- return arg;
-
if (TYPE_P (decl))
{
decl_type = decl;
@@ -8677,14 +8810,14 @@ check_default_argument (tree decl, tree arg)
A default argument expression is implicitly converted to the
parameter type. */
if (!TREE_TYPE (arg)
- || !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
+ || !can_convert_arg (decl_type, TREE_TYPE (arg), arg, LOOKUP_NORMAL))
{
if (decl)
- error ("default argument for `%#D' has type `%T'",
- decl, TREE_TYPE (arg));
+ error ("default argument for %q#D has type %qT",
+ decl, TREE_TYPE (arg));
else
- error ("default argument for parameter of type `%T' has type `%T'",
- decl_type, TREE_TYPE (arg));
+ error ("default argument for parameter of type %qT has type %qT",
+ decl_type, TREE_TYPE (arg));
return error_mark_node;
}
@@ -8700,8 +8833,7 @@ check_default_argument (tree decl, tree arg)
NULL);
if (var)
{
- error ("default argument `%E' uses local variable `%D'",
- arg, var);
+ error ("default argument %qE uses local variable %qD", arg, var);
return error_mark_node;
}
@@ -8713,69 +8845,55 @@ check_default_argument (tree decl, tree arg)
Given the list of things declared inside the parens,
return a list of types.
- We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P
- flag. If unset, we append void_list_node. A parmlist declared
- as `(void)' is accepted as the empty parmlist.
+ If this parameter does not end with an ellipsis, we append
+ void_list_node.
*PARMS is set to the chain of PARM_DECLs created. */
static tree
-grokparms (tree first_parm, tree *parms)
+grokparms (cp_parameter_declarator *first_parm, tree *parms)
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
- int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);
- tree parm, chain;
+ int ellipsis = !first_parm || first_parm->ellipsis_p;
+ cp_parameter_declarator *parm;
int any_error = 0;
- my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115);
-
- for (parm = first_parm; parm != NULL_TREE; parm = chain)
+ for (parm = first_parm; parm != NULL; parm = parm->next)
{
tree type = NULL_TREE;
- tree decl = TREE_VALUE (parm);
- tree init = TREE_PURPOSE (parm);
- tree specs, attrs;
-
- chain = TREE_CHAIN (parm);
- /* @@ weak defense against parse errors. */
- if (TREE_CODE (decl) != VOID_TYPE
- && TREE_CODE (decl) != TREE_LIST)
- {
- /* Give various messages as the need arises. */
- if (TREE_CODE (decl) == STRING_CST)
- error ("invalid string constant `%E'", decl);
- else if (TREE_CODE (decl) == INTEGER_CST)
- error ("invalid integer constant in parameter list, did you forget to give parameter name?");
- continue;
- }
+ tree init = parm->default_argument;
+ tree attrs;
+ tree decl;
- if (parm == void_list_node)
- break;
+ if (parm == no_parameters)
+ break;
- split_specs_attrs (TREE_PURPOSE (decl), &specs, &attrs);
- decl = grokdeclarator (TREE_VALUE (decl), specs,
+ attrs = parm->decl_specifiers.attributes;
+ parm->decl_specifiers.attributes = NULL_TREE;
+ decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
PARM, init != NULL_TREE, &attrs);
if (! decl || TREE_TYPE (decl) == error_mark_node)
- continue;
+ continue;
if (attrs)
cplus_decl_attributes (&decl, attrs, 0);
type = TREE_TYPE (decl);
if (VOID_TYPE_P (type))
- {
- if (same_type_p (type, void_type_node)
- && !DECL_NAME (decl) && !result && !chain && !ellipsis)
- /* this is a parmlist of `(void)', which is ok. */
- break;
- cxx_incomplete_type_error (decl, type);
+ {
+ if (same_type_p (type, void_type_node)
+ && DECL_SELF_REFERENCE_P (type)
+ && !DECL_NAME (decl) && !result && !parm->next && !ellipsis)
+ /* this is a parmlist of `(void)', which is ok. */
+ break;
+ cxx_incomplete_type_error (decl, type);
/* It's not a good idea to actually create parameters of
type `void'; other parts of the compiler assume that a
void type terminates the parameter list. */
type = error_mark_node;
TREE_TYPE (decl) = error_mark_node;
- }
+ }
if (type != error_mark_node)
{
@@ -8784,7 +8902,7 @@ grokparms (tree first_parm, tree *parms)
type = cp_build_qualified_type (type, 0);
if (TREE_CODE (type) == METHOD_TYPE)
{
- error ("parameter `%D' invalidly declared method type", decl);
+ error ("parameter %qD invalidly declared method type", decl);
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
@@ -8797,25 +8915,26 @@ grokparms (tree first_parm, tree *parms)
tree t = TREE_TYPE (type);
int ptr = TYPE_PTR_P (type);
- while (1)
- {
- if (TYPE_PTR_P (t))
- ptr = 1;
- else if (TREE_CODE (t) != ARRAY_TYPE)
- break;
- else if (!TYPE_DOMAIN (t))
- break;
- t = TREE_TYPE (t);
- }
+ while (1)
+ {
+ if (TYPE_PTR_P (t))
+ ptr = 1;
+ else if (TREE_CODE (t) != ARRAY_TYPE)
+ break;
+ else if (!TYPE_DOMAIN (t))
+ break;
+ t = TREE_TYPE (t);
+ }
if (TREE_CODE (t) == ARRAY_TYPE)
- error ("parameter `%D' includes %s to array of unknown bound `%T'",
- decl, ptr ? "pointer" : "reference", t);
+ error ("parameter %qD includes %s to array of unknown "
+ "bound %qT",
+ decl, ptr ? "pointer" : "reference", t);
}
- if (!any_error && init)
- init = check_default_argument (decl, init);
- else
+ if (any_error)
init = NULL_TREE;
+ else if (init && !processing_template_decl)
+ init = check_default_argument (decl, init);
}
TREE_CHAIN (decl) = decls;
@@ -8856,21 +8975,25 @@ copy_fn_p (tree d)
tree args;
tree arg_type;
int result = 1;
-
- my_friendly_assert (DECL_FUNCTION_MEMBER_P (d), 20011208);
- if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d)))
+ gcc_assert (DECL_FUNCTION_MEMBER_P (d));
+
+ if (TREE_CODE (d) == TEMPLATE_DECL
+ || (DECL_TEMPLATE_INFO (d)
+ && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d))))
/* Instantiations of template member functions are never copy
functions. Note that member functions of templated classes are
represented as template functions internally, and we must
accept those as copy functions. */
return 0;
-
+
args = FUNCTION_FIRST_USER_PARMTYPE (d);
if (!args)
return 0;
arg_type = TREE_VALUE (args);
+ if (arg_type == error_mark_node)
+ return 0;
if (TYPE_MAIN_VARIANT (arg_type) == DECL_CONTEXT (d))
{
@@ -8885,7 +9008,7 @@ copy_fn_p (tree d)
}
else
return 0;
-
+
args = TREE_CHAIN (args);
if (args && args != void_list_node && !TREE_PURPOSE (args))
@@ -8899,45 +9022,49 @@ copy_fn_p (tree d)
void grok_special_member_properties (tree decl)
{
- if (!DECL_NONSTATIC_MEMBER_FUNCTION_P(decl))
- ; /* Not special. */
- else if (DECL_CONSTRUCTOR_P (decl))
+ tree class_type;
+
+ if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ return;
+
+ class_type = DECL_CONTEXT (decl);
+ if (DECL_CONSTRUCTOR_P (decl))
{
int ctor = copy_fn_p (decl);
-
+
+ TYPE_HAS_CONSTRUCTOR (class_type) = 1;
+
if (ctor > 0)
{
/* [class.copy]
-
- A non-template constructor for class X is a copy
- constructor if its first parameter is of type X&, const
- X&, volatile X& or const volatile X&, and either there
- are no other parameters or else all other parameters have
- default arguments. */
- TYPE_HAS_INIT_REF (DECL_CONTEXT (decl)) = 1;
+
+ A non-template constructor for class X is a copy
+ constructor if its first parameter is of type X&, const
+ X&, volatile X& or const volatile X&, and either there
+ are no other parameters or else all other parameters have
+ default arguments. */
+ TYPE_HAS_INIT_REF (class_type) = 1;
if (ctor > 1)
- TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_CONST_INIT_REF (class_type) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
- TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
}
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
/* [class.copy]
-
- A non-template assignment operator for class X is a copy
- assignment operator if its parameter is of type X, X&, const
- X&, volatile X& or const volatile X&. */
-
+
+ A non-template assignment operator for class X is a copy
+ assignment operator if its parameter is of type X, X&, const
+ X&, volatile X& or const volatile X&. */
+
int assop = copy_fn_p (decl);
-
+
if (assop)
{
- TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_ASSIGN_REF (class_type) = 1;
if (assop != 1)
- TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
- if (DECL_PURE_VIRTUAL_P (decl))
- TYPE_HAS_ABSTRACT_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_CONST_ASSIGN_REF (class_type) = 1;
}
}
}
@@ -8953,26 +9080,25 @@ grok_ctor_properties (tree ctype, tree decl)
if (ctor_parm < 0)
{
/* [class.copy]
-
- A declaration of a constructor for a class X is ill-formed if
- its first parameter is of type (optionally cv-qualified) X
- and either there are no other parameters or else all other
- parameters have default arguments.
-
- We *don't* complain about member template instantiations that
- have this form, though; they can occur as we try to decide
- what constructor to use during overload resolution. Since
- overload resolution will never prefer such a constructor to
- the non-template copy constructor (which is either explicitly
- or implicitly defined), there's no need to worry about their
- existence. Theoretically, they should never even be
- instantiated, but that's hard to forestall. */
- error ("invalid constructor; you probably meant `%T (const %T&)'",
+
+ A declaration of a constructor for a class X is ill-formed if
+ its first parameter is of type (optionally cv-qualified) X
+ and either there are no other parameters or else all other
+ parameters have default arguments.
+
+ We *don't* complain about member template instantiations that
+ have this form, though; they can occur as we try to decide
+ what constructor to use during overload resolution. Since
+ overload resolution will never prefer such a constructor to
+ the non-template copy constructor (which is either explicitly
+ or implicitly defined), there's no need to worry about their
+ existence. Theoretically, they should never even be
+ instantiated, but that's hard to forestall. */
+ error ("invalid constructor; you probably meant %<%T (const %T&)%>",
ctype, ctype);
- SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
return 0;
}
-
+
return 1;
}
@@ -8983,7 +9109,7 @@ ambi_op_p (enum tree_code code)
{
return (code == INDIRECT_REF
|| code == ADDR_EXPR
- || code == CONVERT_EXPR
+ || code == UNARY_PLUS_EXPR
|| code == NEGATE_EXPR
|| code == PREINCREMENT_EXPR
|| code == PREDECREMENT_EXPR);
@@ -9000,8 +9126,7 @@ unary_op_p (enum tree_code code)
|| code == TYPE_EXPR);
}
-/* DECL is a declaration for an overloaded operator. Returns true if
- the declaration is valid; false otherwise. If COMPLAIN is true,
+/* DECL is a declaration for an overloaded operator. If COMPLAIN is true,
errors are issued for invalid declarations. */
bool
@@ -9014,13 +9139,9 @@ grok_op_properties (tree decl, bool complain)
enum tree_code operator_code;
int arity;
bool ellipsis_p;
- bool ok;
tree class_type;
- /* Assume that the declaration is valid. */
- ok = true;
-
- /* Count the number of arguments. and check for ellipsis */
+ /* Count the number of arguments and check for ellipsis. */
for (argtype = argtypes, arity = 0;
argtype && argtype != void_list_node;
argtype = TREE_CHAIN (argtype))
@@ -9030,7 +9151,7 @@ grok_op_properties (tree decl, bool complain)
class_type = DECL_CONTEXT (decl);
if (class_type && !CLASS_TYPE_P (class_type))
class_type = NULL_TREE;
-
+
if (DECL_CONV_FN_P (decl))
operator_code = TYPE_EXPR;
else
@@ -9052,10 +9173,10 @@ grok_op_properties (tree decl, bool complain)
#include "operators.def"
#undef DEF_OPERATOR
- abort ();
+ gcc_unreachable ();
}
while (0);
- my_friendly_assert (operator_code != LAST_CPLUS_TREE_CODE, 20000526);
+ gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
if (class_type)
@@ -9081,6 +9202,31 @@ grok_op_properties (tree decl, bool complain)
break;
}
+ /* [basic.std.dynamic.allocation]/1:
+
+ A program is ill-formed if an allocation function is declared
+ in a namespace scope other than global scope or declared static
+ in global scope.
+
+ The same also holds true for deallocation functions. */
+ if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR
+ || operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
+ {
+ if (DECL_NAMESPACE_SCOPE_P (decl))
+ {
+ if (CP_DECL_CONTEXT (decl) != global_namespace)
+ {
+ error ("%qD may not be declared within a namespace", decl);
+ return false;
+ }
+ else if (!TREE_PUBLIC (decl))
+ {
+ error ("%qD may not be declared as static", decl);
+ return false;
+ }
+ }
+ }
+
if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
@@ -9097,17 +9243,27 @@ grok_op_properties (tree decl, bool complain)
|| operator_code == COMPONENT_REF
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
- error ("`%D' must be a nonstatic member function", decl);
+ {
+ error ("%qD must be a nonstatic member function", decl);
+ return false;
+ }
else
{
tree p;
if (DECL_STATIC_FUNCTION_P (decl))
- error ("`%D' must be either a non-static member function or a non-member function", decl);
+ {
+ error ("%qD must be either a non-static member "
+ "function or a non-member function", decl);
+ return false;
+ }
for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
{
tree arg = non_reference (TREE_VALUE (p));
+ if (arg == error_mark_node)
+ return false;
+
/* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
because these checks are performed even on
template functions. */
@@ -9117,13 +9273,10 @@ grok_op_properties (tree decl, bool complain)
if (!p || p == void_list_node)
{
- if (!complain)
- return false;
-
- error ("`%D' must have an argument of class or "
- "enumerated type",
- decl);
- ok = false;
+ if (complain)
+ error ("%qD must have an argument of class or "
+ "enumerated type", decl);
+ return false;
}
}
}
@@ -9131,10 +9284,10 @@ grok_op_properties (tree decl, bool complain)
/* There are no restrictions on the arguments to an overloaded
"operator ()". */
if (operator_code == CALL_EXPR)
- return ok;
+ return true;
/* Warn about conversion operators that will never be used. */
- if (IDENTIFIER_TYPENAME_P (name)
+ if (IDENTIFIER_TYPENAME_P (name)
&& ! DECL_TEMPLATE_INFO (decl)
&& warn_conversion
/* Warn only declaring the function; there is no need to
@@ -9144,10 +9297,10 @@ grok_op_properties (tree decl, bool complain)
tree t = TREE_TYPE (name);
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
const char *what = 0;
-
+
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
-
+
if (TREE_CODE (t) == VOID_TYPE)
what = "void";
else if (class_type)
@@ -9162,7 +9315,8 @@ grok_op_properties (tree decl, bool complain)
}
if (what)
- warning ("conversion to %s%s will never use a type conversion operator",
+ warning (OPT_Wconversion, "conversion to %s%s will never use a type "
+ "conversion operator",
ref ? "a reference to " : "", what);
}
@@ -9170,9 +9324,13 @@ grok_op_properties (tree decl, bool complain)
{
/* 13.4.0.3 */
error ("ISO C++ prohibits overloading operator ?:");
+ return false;
}
else if (ellipsis_p)
- error ("`%D' must not have variable number of arguments", decl);
+ {
+ error ("%qD must not have variable number of arguments", decl);
+ return false;
+ }
else if (ambi_op_p (operator_code))
{
if (arity == 1)
@@ -9193,7 +9351,7 @@ grok_op_properties (tree decl, bool complain)
operator_code = BIT_AND_EXPR;
break;
- case CONVERT_EXPR:
+ case UNARY_PLUS_EXPR:
operator_code = PLUS_EXPR;
break;
@@ -9210,7 +9368,7 @@ grok_op_properties (tree decl, bool complain)
break;
default:
- abort ();
+ gcc_unreachable ();
}
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
@@ -9221,20 +9379,21 @@ grok_op_properties (tree decl, bool complain)
&& ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
- error ("postfix `%D' must take `int' as its argument",
- decl);
+ error ("postfix %qD must take %<int%> as its argument",
+ decl);
else
- error
- ("postfix `%D' must take `int' as its second argument",
- decl);
+ error ("postfix %qD must take %<int%> as its second "
+ "argument", decl);
+ return false;
}
}
else
{
if (methodp)
- error ("`%D' must take either zero or one argument", decl);
+ error ("%qD must take either zero or one argument", decl);
else
- error ("`%D' must take either one or two arguments", decl);
+ error ("%qD must take either one or two arguments", decl);
+ return false;
}
/* More Effective C++ rule 6. */
@@ -9255,13 +9414,13 @@ grok_op_properties (tree decl, bool complain)
if (TREE_CODE (ret) != REFERENCE_TYPE
|| !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
arg))
- warning ("prefix `%D' should return `%T'", decl,
- build_reference_type (arg));
+ warning (OPT_Weffc__, "prefix %qD should return %qT", decl,
+ build_reference_type (arg));
}
else
{
if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
- warning ("postfix `%D' should return `%T'", decl, arg);
+ warning (OPT_Weffc__, "postfix %qD should return %qT", decl, arg);
}
}
}
@@ -9270,9 +9429,10 @@ grok_op_properties (tree decl, bool complain)
if (arity != 1)
{
if (methodp)
- error ("`%D' must take `void'", decl);
+ error ("%qD must take %<void%>", decl);
else
- error ("`%D' must take exactly one argument", decl);
+ error ("%qD must take exactly one argument", decl);
+ return false;
}
}
else /* if (binary_op_p (operator_code)) */
@@ -9280,9 +9440,10 @@ grok_op_properties (tree decl, bool complain)
if (arity != 2)
{
if (methodp)
- error ("`%D' must take exactly one argument", decl);
+ error ("%qD must take exactly one argument", decl);
else
- error ("`%D' must take exactly two arguments", decl);
+ error ("%qD must take exactly two arguments", decl);
+ return false;
}
/* More Effective C++ rule 7. */
@@ -9290,8 +9451,8 @@ grok_op_properties (tree decl, bool complain)
&& (operator_code == TRUTH_ANDIF_EXPR
|| operator_code == TRUTH_ORIF_EXPR
|| operator_code == COMPOUND_EXPR))
- warning ("user-defined `%D' always evaluates both arguments",
- decl);
+ warning (OPT_Weffc__, "user-defined %qD always evaluates both arguments",
+ decl);
}
/* Effective C++ rule 23. */
@@ -9304,29 +9465,32 @@ grok_op_properties (tree decl, bool complain)
|| operator_code == MULT_EXPR
|| operator_code == TRUNC_MOD_EXPR)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
- warning ("`%D' should return by value", decl);
+ warning (OPT_Weffc__, "%qD should return by value", decl);
/* [over.oper]/8 */
for (; argtypes && argtypes != void_list_node;
- argtypes = TREE_CHAIN (argtypes))
- if (TREE_PURPOSE (argtypes))
- {
- TREE_PURPOSE (argtypes) = NULL_TREE;
- if (operator_code == POSTINCREMENT_EXPR
+ argtypes = TREE_CHAIN (argtypes))
+ if (TREE_PURPOSE (argtypes))
+ {
+ TREE_PURPOSE (argtypes) = NULL_TREE;
+ if (operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR)
- {
- if (pedantic)
- pedwarn ("`%D' cannot have default arguments", decl);
- }
- else
- error ("`%D' cannot have default arguments", decl);
- }
-
+ {
+ if (pedantic)
+ pedwarn ("%qD cannot have default arguments", decl);
+ }
+ else
+ {
+ error ("%qD cannot have default arguments", decl);
+ return false;
+ }
+ }
}
-
- return ok;
+ return true;
}
+/* Return a string giving the keyword associate with CODE. */
+
static const char *
tag_name (enum tag_types code)
{
@@ -9343,7 +9507,7 @@ tag_name (enum tag_types code)
case typename_type:
return "typename";
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -9371,7 +9535,15 @@ check_elaborated_type_specifier (enum tag_types tag_code,
type = TREE_TYPE (decl);
- /* [dcl.type.elab]
+ /* Check TEMPLATE_TYPE_PARM first because DECL_IMPLICIT_TYPEDEF_P
+ is false for this case as well. */
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ {
+ error ("using template type parameter %qT after %qs",
+ type, tag_name (tag_code));
+ return error_mark_node;
+ }
+ /* [dcl.type.elab]
If the identifier resolves to a typedef-name or a template
type-parameter, the elaborated-type-specifier is ill-formed.
@@ -9379,17 +9551,11 @@ check_elaborated_type_specifier (enum tag_types tag_code,
In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when
the type is declared. */
- if (!DECL_IMPLICIT_TYPEDEF_P (decl)
- && tag_code != typename_type)
- {
- error ("using typedef-name `%D' after `%s'", decl, tag_name (tag_code));
- return IS_AGGR_TYPE (type) ? type : error_mark_node;
- }
-
- if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+ && tag_code != typename_type)
{
- error ("using template type parameter `%T' after `%s'",
- type, tag_name (tag_code));
+ error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
+ error ("%q+D has a previous declaration here", decl);
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
@@ -9397,13 +9563,15 @@ check_elaborated_type_specifier (enum tag_types tag_code,
&& tag_code != enum_type
&& tag_code != typename_type)
{
- error ("`%T' referred to as `%s'", type, tag_name (tag_code));
+ error ("%qT referred to as %qs", type, tag_name (tag_code));
+ error ("%q+T has a previous declaration here", type);
return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
&& tag_code == enum_type)
{
- error ("`%T' referred to as enum", type);
+ error ("%qT referred to as enum", type);
+ error ("%q+T has a previous declaration here", type);
return error_mark_node;
}
else if (!allow_template_p
@@ -9417,8 +9585,7 @@ check_elaborated_type_specifier (enum tag_types tag_code,
void f(class C); // No template header here
then the required template argument is missing. */
-
- error ("template argument required for `%s %T'",
+ error ("template argument required for %<%s %T%>",
tag_name (tag_code),
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
return error_mark_node;
@@ -9427,31 +9594,103 @@ check_elaborated_type_specifier (enum tag_types tag_code,
return type;
}
+/* Lookup NAME in elaborate type specifier in scope according to
+ SCOPE and issue diagnostics if necessary.
+ Return *_TYPE node upon success, NULL_TREE when the NAME is not
+ found, and ERROR_MARK_NODE for type error. */
+
+static tree
+lookup_and_check_tag (enum tag_types tag_code, tree name,
+ tag_scope scope, bool template_header_p)
+{
+ tree t;
+ tree decl;
+ if (scope == ts_global)
+ {
+ /* First try ordinary name lookup, ignoring hidden class name
+ injected via friend declaration. */
+ decl = lookup_name_prefer_type (name, 2);
+ /* If that fails, the name will be placed in the smallest
+ non-class, non-function-prototype scope according to 3.3.1/5.
+ We may already have a hidden name declared as friend in this
+ scope. So lookup again but not ignoring hidden names.
+ If we find one, that name will be made visible rather than
+ creating a new tag. */
+ if (!decl)
+ decl = lookup_type_scope (name, ts_within_enclosing_non_class);
+ }
+ else
+ decl = lookup_type_scope (name, scope);
+
+ if (decl && DECL_CLASS_TEMPLATE_P (decl))
+ decl = DECL_TEMPLATE_RESULT (decl);
+
+ if (decl && TREE_CODE (decl) == TYPE_DECL)
+ {
+ /* Look for invalid nested type:
+ class C {
+ class C {};
+ }; */
+ if (scope == ts_current && DECL_SELF_REFERENCE_P (decl))
+ {
+ error ("%qD has the same name as the class in which it is "
+ "declared",
+ decl);
+ return error_mark_node;
+ }
+
+ /* Two cases we need to consider when deciding if a class
+ template is allowed as an elaborated type specifier:
+ 1. It is a self reference to its own class.
+ 2. It comes with a template header.
+
+ For example:
+
+ template <class T> class C {
+ class C *c1; // DECL_SELF_REFERENCE_P is true
+ class D;
+ };
+ template <class U> class C; // template_header_p is true
+ template <class T> class C<T>::D {
+ class C *c2; // DECL_SELF_REFERENCE_P is true
+ }; */
+
+ t = check_elaborated_type_specifier (tag_code,
+ decl,
+ template_header_p
+ | DECL_SELF_REFERENCE_P (decl));
+ return t;
+ }
+ else
+ return NULL_TREE;
+}
+
/* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
If a declaration is given, process it here, and report an error if
multiple declarations are not identical.
- GLOBALIZE is false when this is also a definition. Only look in
+ SCOPE is TS_CURRENT when this is also a definition. Only look in
the current frame for the name (since C++ allows new names in any
- scope.)
+ scope.) It is TS_WITHIN_ENCLOSING_NON_CLASS if this is a friend
+ declaration. Only look beginning from the current scope outward up
+ till the nearest non-class scope. Otherwise it is TS_GLOBAL.
TEMPLATE_HEADER_P is true when this declaration is preceded by
a set of template parameters. */
tree
xref_tag (enum tag_types tag_code, tree name,
- bool globalize, bool template_header_p)
+ tag_scope scope, bool template_header_p)
{
enum tree_code code;
tree t;
- struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
switch (tag_code)
{
@@ -9466,93 +9705,62 @@ xref_tag (enum tag_types tag_code, tree name,
code = ENUMERAL_TYPE;
break;
default:
- abort ();
+ gcc_unreachable ();
}
- if (! globalize)
- {
- /* If we know we are defining this tag, only look it up in
- this scope and don't try to find it as a type. */
- t = lookup_tag (code, name, b, 1);
- }
+ /* In case of anonymous name, xref_tag is only called to
+ make type node and push name. Name lookup is not required. */
+ if (ANON_AGGRNAME_P (name))
+ t = NULL_TREE;
else
- {
- tree decl = lookup_name (name, 2);
+ t = lookup_and_check_tag (tag_code, name,
+ scope, template_header_p);
- if (decl && DECL_CLASS_TEMPLATE_P (decl))
- decl = DECL_TEMPLATE_RESULT (decl);
+ if (t == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- if (decl && TREE_CODE (decl) == TYPE_DECL)
- {
- /* Two cases we need to consider when deciding if a class
- template is allowed as an elaborated type specifier:
- 1. It is a self reference to its own class.
- 2. It comes with a template header.
-
- For example:
-
- template <class T> class C {
- class C *c1; // DECL_SELF_REFERENCE_P is true
- class D;
- };
- template <class U> class C; // template_header_p is true
- template <class T> class C<T>::D {
- class C *c2; // DECL_SELF_REFERENCE_P is true
- }; */
-
- t = check_elaborated_type_specifier (tag_code,
- decl,
- template_header_p
- | DECL_SELF_REFERENCE_P (decl));
- if (t == error_mark_node)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- }
- else
- t = NULL_TREE;
-
- if (t && current_class_type
- && template_class_depth (current_class_type)
- && template_header_p)
- {
- /* Since GLOBALIZE is nonzero, we are not looking at a
- definition of this tag. Since, in addition, we are currently
- processing a (member) template declaration of a template
- class, we must be very careful; consider:
+ if (scope != ts_current && t && current_class_type
+ && template_class_depth (current_class_type)
+ && template_header_p)
+ {
+ /* Since SCOPE is not TS_CURRENT, we are not looking at a
+ definition of this tag. Since, in addition, we are currently
+ processing a (member) template declaration of a template
+ class, we must be very careful; consider:
- template <class X>
- struct S1
+ template <class X>
+ struct S1
- template <class U>
- struct S2
- { template <class V>
- friend struct S1; };
+ template <class U>
+ struct S2
+ { template <class V>
+ friend struct S1; };
- Here, the S2::S1 declaration should not be confused with the
- outer declaration. In particular, the inner version should
- have a template parameter of level 2, not level 1. This
- would be particularly important if the member declaration
- were instead:
+ Here, the S2::S1 declaration should not be confused with the
+ outer declaration. In particular, the inner version should
+ have a template parameter of level 2, not level 1. This
+ would be particularly important if the member declaration
+ were instead:
- template <class V = U> friend struct S1;
+ template <class V = U> friend struct S1;
- say, when we should tsubst into `U' when instantiating
- S2. On the other hand, when presented with:
+ say, when we should tsubst into `U' when instantiating
+ S2. On the other hand, when presented with:
- template <class T>
- struct S1 {
- template <class U>
- struct S2 {};
- template <class U>
- friend struct S2;
- };
+ template <class T>
+ struct S1 {
+ template <class U>
+ struct S2 {};
+ template <class U>
+ friend struct S2;
+ };
- we must find the inner binding eventually. We
- accomplish this by making sure that the new type we
- create to represent this declaration has the right
- TYPE_CONTEXT. */
- context = TYPE_CONTEXT (t);
- t = NULL_TREE;
- }
+ we must find the inner binding eventually. We
+ accomplish this by making sure that the new type we
+ create to represent this declaration has the right
+ TYPE_CONTEXT. */
+ context = TYPE_CONTEXT (t);
+ t = NULL_TREE;
}
if (! t)
@@ -9563,26 +9771,44 @@ xref_tag (enum tag_types tag_code, tree name,
the forward-reference will be altered into a real type. */
if (code == ENUMERAL_TYPE)
{
- error ("use of enum `%#D' without previous declaration", name);
+ error ("use of enum %q#D without previous declaration", name);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
{
t = make_aggr_type (code);
TYPE_CONTEXT (t) = context;
- pushtag (name, t, globalize);
+ t = pushtag (name, t, scope);
}
}
else
{
- if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
- redeclare_class_template (t, current_template_parms);
- else if (!processing_template_decl
+ if (template_header_p && IS_AGGR_TYPE (t))
+ {
+ if (!redeclare_class_template (t, current_template_parms))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ }
+ else if (!processing_template_decl
&& CLASS_TYPE_P (t)
&& CLASSTYPE_IS_TEMPLATE (t))
{
- error ("redeclaration of `%T' as a non-template", t);
- t = error_mark_node;
+ error ("redeclaration of %qT as a non-template", t);
+ error ("previous declaration %q+D", t);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ }
+
+ /* Make injected friend class visible. */
+ if (scope != ts_within_enclosing_non_class
+ && hidden_name_p (TYPE_NAME (t)))
+ {
+ DECL_ANTICIPATED (TYPE_NAME (t)) = 0;
+ DECL_FRIEND_P (TYPE_NAME (t)) = 0;
+
+ if (TYPE_TEMPLATE_INFO (t))
+ {
+ DECL_ANTICIPATED (TYPE_TI_TEMPLATE (t)) = 0;
+ DECL_FRIEND_P (TYPE_TI_TEMPLATE (t)) = 0;
+ }
}
}
@@ -9590,7 +9816,7 @@ xref_tag (enum tag_types tag_code, tree name,
}
tree
-xref_tag_from_type (tree old, tree id, int globalize)
+xref_tag_from_type (tree old, tree id, tag_scope scope)
{
enum tag_types tag_kind;
@@ -9602,195 +9828,209 @@ xref_tag_from_type (tree old, tree id, int globalize)
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
- return xref_tag (tag_kind, id, globalize, false);
+ return xref_tag (tag_kind, id, scope, false);
}
-/* REF is a type (named NAME), for which we have just seen some
- baseclasses. BASE_LIST is a list of those baseclasses; the
- TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
- the base-class. TREE_VIA_VIRTUAL indicates virtual
- inheritance. CODE_TYPE_NODE indicates whether REF is a class,
- struct, or union. */
+/* Create the binfo hierarchy for REF with (possibly NULL) base list
+ BASE_LIST. For each element on BASE_LIST the TREE_PURPOSE is an
+ access_* node, and the TREE_VALUE is the type of the base-class.
+ Non-NULL TREE_TYPE indicates virtual inheritance.
+
+ Returns true if the binfo heirarchy was successfully created,
+ false if an error was detected. */
-void
+bool
xref_basetypes (tree ref, tree base_list)
{
- /* In the declaration `A : X, Y, ... Z' we mark all the types
- (A, X, Y, ..., Z) so we can check for duplicates. */
tree *basep;
-
+ tree binfo, base_binfo;
+ unsigned max_vbases = 0; /* Maximum direct & indirect virtual bases. */
+ unsigned max_bases = 0; /* Maximum direct bases. */
int i;
- enum tag_types tag_code;
+ tree default_access;
+ tree igo_prev; /* Track Inheritance Graph Order. */
if (ref == error_mark_node)
- return;
+ return false;
- if (TREE_CODE (ref) == UNION_TYPE)
- {
- error ("derived union `%T' invalid", ref);
- return;
- }
-
- tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);
+ /* The base of a derived class is private by default, all others are
+ public. */
+ default_access = (TREE_CODE (ref) == RECORD_TYPE
+ && CLASSTYPE_DECLARED_CLASS (ref)
+ ? access_private_node : access_public_node);
/* First, make sure that any templates in base-classes are
instantiated. This ensures that if we call ourselves recursively
we do not get confused about which classes are marked and which
are not. */
- basep = &base_list;
- while (*basep)
+ basep = &base_list;
+ while (*basep)
{
tree basetype = TREE_VALUE (*basep);
+
if (!(processing_template_decl && uses_template_parms (basetype))
&& !complete_type_or_else (basetype, NULL))
/* An incomplete type. Remove it from the list. */
*basep = TREE_CHAIN (*basep);
else
- basep = &TREE_CHAIN (*basep);
+ {
+ max_bases++;
+ if (TREE_TYPE (*basep))
+ max_vbases++;
+ if (CLASS_TYPE_P (basetype))
+ max_vbases += VEC_length (tree, CLASSTYPE_VBASECLASSES (basetype));
+ basep = &TREE_CHAIN (*basep);
+ }
}
- SET_CLASSTYPE_MARKED (ref);
- i = list_length (base_list);
- if (i)
+ TYPE_MARKED_P (ref) = 1;
+
+ /* The binfo slot should be empty, unless this is an (ill-formed)
+ redefinition. */
+ gcc_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref));
+ gcc_assert (TYPE_MAIN_VARIANT (ref) == ref);
+
+ binfo = make_tree_binfo (max_bases);
+
+ TYPE_BINFO (ref) = binfo;
+ BINFO_OFFSET (binfo) = size_zero_node;
+ BINFO_TYPE (binfo) = ref;
+
+ if (max_bases)
{
- tree binfo = TYPE_BINFO (ref);
- tree binfos = make_tree_vec (i);
- tree accesses = make_tree_vec (i);
-
- BINFO_BASETYPES (binfo) = binfos;
- BINFO_BASEACCESSES (binfo) = accesses;
-
- for (i = 0; base_list; base_list = TREE_CHAIN (base_list))
- {
- tree access = TREE_PURPOSE (base_list);
- int via_virtual = TREE_VIA_VIRTUAL (base_list);
- tree basetype = TREE_VALUE (base_list);
- tree base_binfo;
-
- if (access == access_default_node)
- /* The base of a derived struct is public by default. */
- access = (tag_code == class_type
- ? access_private_node : access_public_node);
-
- if (basetype && TREE_CODE (basetype) == TYPE_DECL)
- basetype = TREE_TYPE (basetype);
- if (!basetype
- || (TREE_CODE (basetype) != RECORD_TYPE
- && TREE_CODE (basetype) != TYPENAME_TYPE
- && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
- && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
- {
- error ("base type `%T' fails to be a struct or class type",
- basetype);
- continue;
- }
-
- if (CLASSTYPE_MARKED (basetype))
- {
- if (basetype == ref)
- error ("recursive type `%T' undefined", basetype);
- else
- error ("duplicate base type `%T' invalid", basetype);
- continue;
- }
-
- if (TYPE_FOR_JAVA (basetype)
- && (current_lang_depth () == 0))
- TYPE_FOR_JAVA (ref) = 1;
-
- if (CLASS_TYPE_P (basetype))
- {
- base_binfo = TYPE_BINFO (basetype);
- /* This flag will be in the binfo of the base type, we must
- clear it after copying the base binfos. */
- BINFO_DEPENDENT_BASE_P (base_binfo)
- = dependent_type_p (basetype);
- }
- else
- base_binfo = make_binfo (size_zero_node, basetype,
- NULL_TREE, NULL_TREE);
-
- TREE_VEC_ELT (binfos, i) = base_binfo;
- TREE_VEC_ELT (accesses, i) = access;
- /* This flag will be in the binfo of the base type, we must
- clear it after copying the base binfos. */
- TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
-
- SET_CLASSTYPE_MARKED (basetype);
-
- /* We are free to modify these bits because they are meaningless
- at top level, and BASETYPE is a top-level type. */
- if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
- /* Converting to a virtual base class requires looking
- up the offset of the virtual base. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
- }
-
- if (CLASS_TYPE_P (basetype))
- {
- TYPE_HAS_NEW_OPERATOR (ref)
- |= TYPE_HAS_NEW_OPERATOR (basetype);
- TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
- |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
- TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
- /* If the base-class uses multiple inheritance, so do we. */
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
- /* Likewise, if converting to a base of the base may require
- code, then we may need to generate code to convert to a
- base as well. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
- |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
- }
- i++;
+ BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, max_bases);
+ /* An aggregate cannot have baseclasses. */
+ CLASSTYPE_NON_AGGREGATE (ref) = 1;
+
+ if (TREE_CODE (ref) == UNION_TYPE)
+ {
+ error ("derived union %qT invalid", ref);
+ return false;
+ }
+ }
+
+ if (max_bases > 1)
+ {
+ if (TYPE_FOR_JAVA (ref))
+ {
+ error ("Java class %qT cannot have multiple bases", ref);
+ return false;
+ }
+ }
+
+ if (max_vbases)
+ {
+ CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, gc, max_vbases);
+
+ if (TYPE_FOR_JAVA (ref))
+ {
+ error ("Java class %qT cannot have virtual bases", ref);
+ return false;
+ }
+ }
+
+ for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))
+ {
+ tree access = TREE_PURPOSE (base_list);
+ int via_virtual = TREE_TYPE (base_list) != NULL_TREE;
+ tree basetype = TREE_VALUE (base_list);
+
+ if (access == access_default_node)
+ access = default_access;
+
+ if (TREE_CODE (basetype) == TYPE_DECL)
+ basetype = TREE_TYPE (basetype);
+ if (TREE_CODE (basetype) != RECORD_TYPE
+ && TREE_CODE (basetype) != TYPENAME_TYPE
+ && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
+ {
+ error ("base type %qT fails to be a struct or class type",
+ basetype);
+ return false;
}
- if (i)
- TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
- else
- BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;
-
- if (i > 1)
+
+ if (TYPE_FOR_JAVA (basetype) && (current_lang_depth () == 0))
+ TYPE_FOR_JAVA (ref) = 1;
+
+ base_binfo = NULL_TREE;
+ if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype))
{
- TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
- /* If there is more than one non-empty they cannot be at the same
- address. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
+ base_binfo = TYPE_BINFO (basetype);
+ /* The original basetype could have been a typedef'd type. */
+ basetype = BINFO_TYPE (base_binfo);
+
+ /* Inherit flags from the base. */
+ TYPE_HAS_NEW_OPERATOR (ref)
+ |= TYPE_HAS_NEW_OPERATOR (basetype);
+ TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
+ |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
+ TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+ TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype);
+ CLASSTYPE_DIAMOND_SHAPED_P (ref)
+ |= CLASSTYPE_DIAMOND_SHAPED_P (basetype);
+ CLASSTYPE_REPEATED_BASE_P (ref)
+ |= CLASSTYPE_REPEATED_BASE_P (basetype);
}
- }
-
- /* Copy the base binfos, collect the virtual bases and set the
- inheritance order chain. */
- copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
- CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
- if (TYPE_FOR_JAVA (ref))
- {
- if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
- error ("Java class '%T' cannot have multiple bases", ref);
- if (CLASSTYPE_VBASECLASSES (ref))
- error ("Java class '%T' cannot have virtual bases", ref);
+ /* We must do this test after we've seen through a typedef
+ type. */
+ if (TYPE_MARKED_P (basetype))
+ {
+ if (basetype == ref)
+ error ("recursive type %qT undefined", basetype);
+ else
+ error ("duplicate base type %qT invalid", basetype);
+ return false;
+ }
+ TYPE_MARKED_P (basetype) = 1;
+
+ base_binfo = copy_binfo (base_binfo, basetype, ref,
+ &igo_prev, via_virtual);
+ if (!BINFO_INHERITANCE_CHAIN (base_binfo))
+ BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
+
+ BINFO_BASE_APPEND (binfo, base_binfo);
+ BINFO_BASE_ACCESS_APPEND (binfo, access);
}
+ if (VEC_space (tree, CLASSTYPE_VBASECLASSES (ref), 1))
+ /* If we have space in the vbase vector, we must have shared at
+ least one of them, and are therefore diamond shaped. */
+ CLASSTYPE_DIAMOND_SHAPED_P (ref) = 1;
+
/* Unmark all the types. */
- while (i--)
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0;
+ TYPE_MARKED_P (ref) = 0;
+
+ /* Now see if we have a repeated base type. */
+ if (!CLASSTYPE_REPEATED_BASE_P (ref))
{
- tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i));
-
- CLEAR_CLASSTYPE_MARKED (basetype);
- if (CLASS_TYPE_P (basetype))
+ for (base_binfo = binfo; base_binfo;
+ base_binfo = TREE_CHAIN (base_binfo))
{
- TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0;
- BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0;
+ if (TYPE_MARKED_P (BINFO_TYPE (base_binfo)))
+ {
+ CLASSTYPE_REPEATED_BASE_P (ref) = 1;
+ break;
+ }
+ TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 1;
}
+ for (base_binfo = binfo; base_binfo;
+ base_binfo = TREE_CHAIN (base_binfo))
+ if (TYPE_MARKED_P (BINFO_TYPE (base_binfo)))
+ TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0;
+ else
+ break;
}
- CLEAR_CLASSTYPE_MARKED (ref);
+
+ return true;
}
/* Begin compiling the definition of an enumeration type.
- NAME is its name (or null if anonymous).
+ NAME is its name.
Returns the type object, as yet incomplete.
Also records info about it so that build_enumerator
may be used to declare the individual values as they are read. */
@@ -9798,27 +10038,34 @@ xref_basetypes (tree ref, tree base_list)
tree
start_enum (tree name)
{
- tree enumtype = NULL_TREE;
- struct cp_binding_level *b = current_binding_level;
+ tree enumtype;
+
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
forward reference. */
- if (name != NULL_TREE)
- enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
+ enumtype = lookup_and_check_tag (enum_type, name,
+ /*tag_scope=*/ts_current,
+ /*template_header_p=*/false);
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
{
- error ("multiple definition of `%#T'", enumtype);
+ error ("multiple definition of %q#T", enumtype);
error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype));
/* Clear out TYPE_VALUES, and start again. */
TYPE_VALUES (enumtype) = NULL_TREE;
}
else
{
+ /* In case of error, make a dummy enum to allow parsing to
+ continue. */
+ if (enumtype == error_mark_node)
+ name = make_anon_name ();
+
enumtype = make_node (ENUMERAL_TYPE);
- pushtag (name, enumtype, 0);
+ enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
}
return enumtype;
@@ -9838,8 +10085,9 @@ finish_enum (tree enumtype)
tree maxnode;
tree t;
bool unsignedp;
+ bool use_short_enum;
int lowprec;
- int highprec;
+ int highprec;
int precision;
integer_type_kind itk;
tree underlying_type = NULL_TREE;
@@ -9853,8 +10101,8 @@ finish_enum (tree enumtype)
works. */
if (processing_template_decl)
{
- for (values = TYPE_VALUES (enumtype);
- values;
+ for (values = TYPE_VALUES (enumtype);
+ values;
values = TREE_CHAIN (values))
TREE_TYPE (TREE_VALUE (values)) = enumtype;
if (at_function_scope_p ())
@@ -9867,8 +10115,8 @@ finish_enum (tree enumtype)
{
minnode = maxnode = NULL_TREE;
- for (values = TYPE_VALUES (enumtype);
- values;
+ for (values = TYPE_VALUES (enumtype);
+ values;
values = TREE_CHAIN (values))
{
decl = TREE_VALUE (values);
@@ -9881,6 +10129,8 @@ finish_enum (tree enumtype)
/* Update the minimum and maximum values, if appropriate. */
value = DECL_INITIAL (decl);
+ if (value == error_mark_node)
+ value = integer_zero_node;
/* Figure out what the minimum and maximum values of the
enumerators are. */
if (!minnode)
@@ -9889,16 +10139,6 @@ finish_enum (tree enumtype)
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
-
- /* Set the TREE_TYPE for the values as well. That's so that when
- we call decl_constant_value we get an entity of the right type
- (but with the constant value). But first make a copy so we
- don't clobber shared INTEGER_CSTs. */
- if (TREE_TYPE (value) != enumtype)
- {
- value = DECL_INITIAL (decl) = copy_node (value);
- TREE_TYPE (value) = enumtype;
- }
}
}
else
@@ -9926,18 +10166,24 @@ finish_enum (tree enumtype)
enumeration. It is implementation-defined which integral type is
used as the underlying type for an enumeration except that the
underlying type shall not be larger than int unless the value of
- an enumerator cannot fit in an int or unsigned int.
+ an enumerator cannot fit in an int or unsigned int.
We use "int" or an "unsigned int" as the underlying type, even if
a smaller integral type would work, unless the user has
- explicitly requested that we use the smallest possible type. */
- for (itk = (flag_short_enums ? itk_char : itk_int);
- itk != itk_none;
+ explicitly requested that we use the smallest possible type. The
+ user can request that for all enumerations with a command line
+ flag, or for just one enumeration with an attribute. */
+
+ use_short_enum = flag_short_enums
+ || lookup_attribute ("packed", TYPE_ATTRIBUTES (enumtype));
+
+ for (itk = (use_short_enum ? itk_char : itk_int);
+ itk != itk_none;
itk++)
{
underlying_type = integer_types[itk];
if (TYPE_PRECISION (underlying_type) >= precision
- && TREE_UNSIGNED (underlying_type) == unsignedp)
+ && TYPE_UNSIGNED (underlying_type) == unsignedp)
break;
}
if (itk == itk_none)
@@ -9947,12 +10193,12 @@ finish_enum (tree enumtype)
IF no integral type can represent all the enumerator values, the
enumeration is ill-formed. */
error ("no integral type can represent all of the enumerator values "
- "for `%T'", enumtype);
+ "for %qT", enumtype);
precision = TYPE_PRECISION (long_long_integer_type_node);
underlying_type = integer_types[itk_unsigned_long_long];
}
- /* Compute the minium and maximum values for the type.
+ /* Compute the minium and maximum values for the type.
[dcl.enum]
@@ -9966,13 +10212,13 @@ finish_enum (tree enumtype)
narrower than their underlying type are suitably zero or sign
extended to fill their mode. g++ doesn't make these guarantees.
Until the middle-end can represent such paradoxical types, we
- set the TYPE_PRECISON to the width of the underlying type. */
+ set the TYPE_PRECISION to the width of the underlying type. */
TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
/* [dcl.enum]
-
+
The value of sizeof() applied to an enumeration type, an object
of an enumeration type, or an enumerator, is the value of sizeof()
applied to the underlying type. */
@@ -9981,15 +10227,24 @@ finish_enum (tree enumtype)
TYPE_MODE (enumtype) = TYPE_MODE (underlying_type);
TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
- TREE_UNSIGNED (enumtype) = TREE_UNSIGNED (underlying_type);
+ TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type);
/* Convert each of the enumerators to the type of the underlying
type of the enumeration. */
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
{
+ location_t saved_location;
+
decl = TREE_VALUE (values);
+ saved_location = input_location;
+ input_location = DECL_SOURCE_LOCATION (decl);
value = perform_implicit_conversion (underlying_type,
DECL_INITIAL (decl));
+ input_location = saved_location;
+
+ /* Do not clobber shared ints. */
+ value = copy_node (value);
+
TREE_TYPE (value) = enumtype;
DECL_INITIAL (decl) = value;
TREE_VALUE (values) = value;
@@ -10007,7 +10262,7 @@ finish_enum (tree enumtype)
TYPE_PRECISION (t) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (t) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (enumtype);
- TREE_UNSIGNED (t) = TREE_UNSIGNED (enumtype);
+ TYPE_UNSIGNED (t) = TYPE_UNSIGNED (enumtype);
}
/* Finish debugging output for this type. */
@@ -10025,6 +10280,11 @@ build_enumerator (tree name, tree value, tree enumtype)
tree context;
tree type;
+ /* If the VALUE was erroneous, pretend it wasn't there; that will
+ result in the enum being assigned the next value in sequence. */
+ if (value == error_mark_node)
+ value = NULL_TREE;
+
/* Remove no-op casts from the value. */
if (value)
STRIP_TYPE_NOPS (value);
@@ -10034,7 +10294,7 @@ build_enumerator (tree name, tree value, tree enumtype)
/* Validate and default VALUE. */
if (value != NULL_TREE)
{
- value = decl_constant_value (value);
+ value = integral_constant_value (value);
if (TREE_CODE (value) == INTEGER_CST)
{
@@ -10043,7 +10303,7 @@ build_enumerator (tree name, tree value, tree enumtype)
}
else
{
- error ("enumerator value for `%D' not integer constant", name);
+ error ("enumerator value for %qD not integer constant", name);
value = NULL_TREE;
}
}
@@ -10051,19 +10311,29 @@ build_enumerator (tree name, tree value, tree enumtype)
/* Default based on previous value. */
if (value == NULL_TREE)
{
- tree prev_value;
-
if (TYPE_VALUES (enumtype))
{
- /* The next value is the previous value ... */
+ HOST_WIDE_INT hi;
+ unsigned HOST_WIDE_INT lo;
+ tree prev_value;
+ bool overflowed;
+
+ /* The next value is the previous value plus one. We can
+ safely assume that the previous value is an INTEGER_CST.
+ add_double doesn't know the type of the target expression,
+ so we must check with int_fits_type_p as well. */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
- /* ... plus one. */
- value = cp_build_binary_op (PLUS_EXPR,
- prev_value,
- integer_one_node);
+ overflowed = add_double (TREE_INT_CST_LOW (prev_value),
+ TREE_INT_CST_HIGH (prev_value),
+ 1, 0, &lo, &hi);
+ value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
+ overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value));
- if (tree_int_cst_lt (value, prev_value))
- error ("overflow in enumeration values at `%D'", name);
+ if (overflowed)
+ {
+ error ("overflow in enumeration values at %qD", name);
+ value = error_mark_node;
+ }
}
else
value = integer_zero_node;
@@ -10075,8 +10345,6 @@ build_enumerator (tree name, tree value, tree enumtype)
/* C++ associates enums with global, function, or class declarations. */
context = current_scope ();
- if (!context)
- context = current_namespace;
/* Build the actual enumeration constant. Note that the enumeration
constants have the type of their initializers until the
@@ -10103,7 +10371,9 @@ build_enumerator (tree name, tree value, tree enumtype)
decl = build_decl (CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
- TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
+ TREE_INVARIANT (decl) = 1;
+ TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
if (context && context == current_class_type)
@@ -10130,27 +10400,24 @@ check_function_type (tree decl, tree current_function_parms)
/* In a function definition, arg types must be complete. */
require_complete_types_for_parms (current_function_parms);
+ if (dependent_type_p (return_type))
+ return;
if (!COMPLETE_OR_VOID_TYPE_P (return_type))
{
- error ("return type `%#T' is incomplete", TREE_TYPE (fntype));
+ tree args = TYPE_ARG_TYPES (fntype);
+
+ error ("return type %q#T is incomplete", return_type);
- /* Make it return void instead, but don't change the
- type of the DECL_RESULT, in case we have a named return value. */
+ /* Make it return void instead. */
if (TREE_CODE (fntype) == METHOD_TYPE)
- {
- tree ctype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype)));
- TREE_TYPE (decl)
- = build_method_type_directly (ctype,
- void_type_node,
- FUNCTION_ARG_CHAIN (decl));
- }
+ fntype = build_method_type_directly (TREE_TYPE (TREE_VALUE (args)),
+ void_type_node,
+ TREE_CHAIN (args));
else
- TREE_TYPE (decl)
- = build_function_type (void_type_node,
- TYPE_ARG_TYPES (TREE_TYPE (decl)));
+ fntype = build_function_type (void_type_node, args);
TREE_TYPE (decl)
= build_exception_variant (fntype,
- TYPE_RAISES_EXCEPTIONS (fntype));
+ TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)));
}
else
abstract_virtuals_error (decl, TREE_TYPE (fntype));
@@ -10169,96 +10436,50 @@ check_function_type (tree decl, tree current_function_parms)
This function creates a binding context for the function body
as well as setting up the FUNCTION_DECL in current_function_decl.
- Returns 1 on success. If the DECLARATOR is not suitable for a function
- (it defines a datum instead), we return 0, which tells
- yyparse to report a parse error.
-
For C++, we must first check whether that datum makes any sense.
For example, "class A local_a(1,2);" means that variable local_a
is an aggregate of type A, which should have a constructor
applied to it with the argument list [1, 2]. */
-int
-start_function (tree declspecs, tree declarator, tree attrs, int flags)
+void
+start_preparsed_function (tree decl1, tree attrs, int flags)
{
- tree decl1;
tree ctype = NULL_TREE;
tree fntype;
tree restype;
int doing_friend = 0;
struct cp_binding_level *bl;
tree current_function_parms;
+ struct c_fileinfo *finfo
+ = get_fileinfo (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1)));
+ bool honor_interface;
/* Sanity check. */
- my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
- my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
-
- /* This should only be done once on the top most decl. */
- if (have_extern_spec)
- {
- declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
- have_extern_spec = false;
- }
-
- if (flags & SF_PRE_PARSED)
- {
- decl1 = declarator;
-
- fntype = TREE_TYPE (decl1);
- if (TREE_CODE (fntype) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (fntype);
+ gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
+ gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE);
- /* ISO C++ 11.4/5. A friend function defined in a class is in
- the (lexical) scope of the class in which it is defined. */
- if (!ctype && DECL_FRIEND_P (decl1))
- {
- ctype = DECL_FRIEND_CONTEXT (decl1);
+ fntype = TREE_TYPE (decl1);
+ if (TREE_CODE (fntype) == METHOD_TYPE)
+ ctype = TYPE_METHOD_BASETYPE (fntype);
- /* CTYPE could be null here if we're dealing with a template;
- for example, `inline friend float foo()' inside a template
- will have no CTYPE set. */
- if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
- ctype = NULL_TREE;
- else
- doing_friend = 1;
- }
- }
- else
+ /* ISO C++ 11.4/5. A friend function defined in a class is in
+ the (lexical) scope of the class in which it is defined. */
+ if (!ctype && DECL_FRIEND_P (decl1))
{
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
- /* If the declarator is not suitable for a function definition,
- cause a syntax error. */
- if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
- return 0;
-
- cplus_decl_attributes (&decl1, attrs, 0);
-
- /* If #pragma weak was used, mark the decl weak now. */
- if (global_scope_p (current_binding_level))
- maybe_apply_pragma_weak (decl1);
+ ctype = DECL_FRIEND_CONTEXT (decl1);
- fntype = TREE_TYPE (decl1);
-
- restype = TREE_TYPE (fntype);
-
- if (TREE_CODE (fntype) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (fntype);
- else if (DECL_MAIN_P (decl1))
- {
- /* If this doesn't return integer_type, or a typedef to
- integer_type, complain. */
- if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
- {
- if (pedantic || warn_return_type)
- pedwarn ("return type for `main' changed to `int'");
- TREE_TYPE (decl1) = fntype = default_function_type;
- }
- }
+ /* CTYPE could be null here if we're dealing with a template;
+ for example, `inline friend float foo()' inside a template
+ will have no CTYPE set. */
+ if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
+ ctype = NULL_TREE;
+ else
+ doing_friend = 1;
}
if (DECL_DECLARED_INLINE_P (decl1)
&& lookup_attribute ("noinline", attrs))
- warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
+ warning (0, "inline function %q+D given attribute noinline", decl1);
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
/* This is a constructor, we must ensure that any default args
@@ -10275,12 +10496,6 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
ctype = NULL_TREE;
}
- /* Warn if function was previously implicitly declared
- (but not if we warned then). */
- if (! warn_implicit
- && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
- cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
-
/* Set up current_class_type, and enter the scope of the class, if
appropriate. */
if (ctype)
@@ -10301,7 +10516,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
if (warn_ecpp
&& DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
- warning ("`operator=' should return a reference to `*this'");
+ warning (OPT_Weffc__, "%<operator=%> should return a reference to %<*this%>");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in poplevel) with the BLOCK. */
@@ -10318,6 +10533,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
by push_nested_class.) */
if (processing_template_decl)
{
+ /* FIXME: Handle error_mark_node more gracefully. */
tree newdecl1 = push_template_decl (decl1);
if (newdecl1 != error_mark_node)
decl1 = newdecl1;
@@ -10333,10 +10549,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
/* Make sure the parameter and return types are reasonable. When
you declare a function, these types can be incomplete, but they
must be complete when you define the function. */
- if (! processing_template_decl)
- check_function_type (decl1, current_function_parms);
- /* Make sure no default arg is missing. */
- check_default_args (decl1);
+ check_function_type (decl1, current_function_parms);
/* Build the return declaration for the function. */
restype = TREE_TYPE (fntype);
@@ -10345,10 +10558,14 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
restype = type_promotes_to (restype);
if (DECL_RESULT (decl1) == NULL_TREE)
{
- DECL_RESULT (decl1)
- = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- c_apply_type_quals_to_decl (cp_type_quals (restype),
- DECL_RESULT (decl1));
+ tree resdecl;
+
+ resdecl = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
+ DECL_ARTIFICIAL (resdecl) = 1;
+ DECL_IGNORED_P (resdecl) = 1;
+ DECL_RESULT (decl1) = resdecl;
+
+ cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
}
/* Initialize RTL machinery. We cannot do this until
@@ -10364,11 +10581,10 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
call expand_expr to calculate the size of a variable-sized array.
We haven't necessarily assigned RTL to all variables yet, so it's
not safe to try to expand expressions involving them. */
- immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
/* Start the statement-tree, start the tree now. */
- begin_stmt_tree (&DECL_SAVED_TREE (decl1));
+ DECL_SAVED_TREE (decl1) = push_stmt_list ();
/* Let the user know we're compiling this function. */
announce_function (decl1);
@@ -10380,7 +10596,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
{
/* A specialization is not used to guide overload resolution. */
if (!DECL_FUNCTION_MEMBER_P (decl1)
- && !(DECL_USE_TEMPLATE (decl1) &&
+ && !(DECL_USE_TEMPLATE (decl1) &&
PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl1))))
{
tree olddecl = pushdecl (decl1);
@@ -10402,6 +10618,17 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
}
fntype = TREE_TYPE (decl1);
+
+ /* If #pragma weak applies, mark the decl appropriately now.
+ The pragma only applies to global functions. Because
+ determining whether or not the #pragma applies involves
+ computing the mangled name for the declaration, we cannot
+ apply the pragma until after we have merged this declaration
+ with any previous declarations; if the original declaration
+ has a linkage specification, that specification applies to
+ the definition as well, and may affect the mangled name. */
+ if (!DECL_CONTEXT (decl1))
+ maybe_apply_pragma_weak (decl1);
}
/* Reset these in case the call to pushdecl changed them. */
@@ -10421,10 +10648,8 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
between `current_class_type' and `current_class_ptr'. */
tree t = DECL_ARGUMENTS (decl1);
- my_friendly_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL,
- 162);
- my_friendly_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE,
- 19990811);
+ gcc_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL);
+ gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
cp_function_chain->x_current_class_ref
= build_indirect_ref (t, NULL);
@@ -10440,12 +10665,20 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
}
if (DECL_HAS_VTT_PARM_P (decl1))
{
- if (DECL_NAME (t) != vtt_parm_identifier)
- abort ();
+ gcc_assert (DECL_NAME (t) == vtt_parm_identifier);
current_vtt_parm = t;
}
}
+ honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
+ /* Implicitly-defined methods (like the
+ destructor for a class in which no destructor
+ is explicitly declared) must not be defined
+ until their definition is needed. So, we
+ ignore interface specifications for
+ compiler-generated functions. */
+ && !DECL_ARTIFICIAL (decl1));
+
if (DECL_INTERFACE_KNOWN (decl1))
{
tree ctx = decl_function_context (decl1);
@@ -10462,16 +10695,15 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
This only affects inlines and template instantiations. */
- else if (interface_unknown == 0
- && ! DECL_TEMPLATE_INSTANTIATION (decl1))
+ else if (!finfo->interface_unknown && honor_interface)
{
- if (DECL_DECLARED_INLINE_P (decl1)
+ if (DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1)
|| processing_template_decl)
{
DECL_EXTERNAL (decl1)
- = (interface_only
- || (DECL_DECLARED_INLINE_P (decl1)
+ = (finfo->interface_only
+ || (DECL_DECLARED_INLINE_P (decl1)
&& ! flag_implement_inlines
&& !DECL_VINDEX (decl1)));
@@ -10480,17 +10712,22 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
}
else
DECL_EXTERNAL (decl1) = 0;
- DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
+ /* If this function is in an interface implemented in this file,
+ make sure that the backend knows to emit this function
+ here. */
+ if (!DECL_EXTERNAL (decl1))
+ mark_needed (decl1);
}
- else if (interface_unknown && interface_only
- && ! DECL_TEMPLATE_INSTANTIATION (decl1))
+ else if (finfo->interface_unknown && finfo->interface_only
+ && honor_interface)
{
/* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
- interface, we will have interface_only set but not
- interface_known. In that case, we don't want to use the normal
- heuristics because someone will supply a #pragma implementation
- elsewhere, and deducing it here would produce a conflict. */
+ interface, we will have both finfo->interface_unknown and
+ finfo->interface_only set. In that case, we don't want to
+ use the normal heuristics because someone will supply a
+ #pragma implementation elsewhere, and deducing it here would
+ produce a conflict. */
comdat_linkage (decl1);
DECL_EXTERNAL (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
@@ -10502,7 +10739,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
So clear DECL_EXTERNAL. */
DECL_EXTERNAL (decl1) = 0;
- if ((DECL_DECLARED_INLINE_P (decl1)
+ if ((DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
&& ! DECL_INTERFACE_KNOWN (decl1)
/* Don't try to defer nested functions for now. */
@@ -10512,23 +10749,86 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
DECL_INTERFACE_KNOWN (decl1) = 1;
}
+ /* Determine the ELF visibility attribute for the function. We must not
+ do this before calling "pushdecl", as we must allow "duplicate_decls"
+ to merge any attributes appropriately. We also need to wait until
+ linkage is set. */
+ if (!DECL_CLONED_FUNCTION_P (decl1))
+ determine_visibility (decl1);
+
begin_scope (sk_function_parms, decl1);
++function_depth;
- if (DECL_DESTRUCTOR_P (decl1))
+ if (DECL_DESTRUCTOR_P (decl1)
+ || (DECL_CONSTRUCTOR_P (decl1)
+ && targetm.cxx.cdtor_returns_this ()))
{
- dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- DECL_CONTEXT (dtor_label) = current_function_decl;
+ cdtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ DECL_CONTEXT (cdtor_label) = current_function_decl;
}
start_fname_decls ();
-
+
store_parm_decls (current_function_parms);
+}
+
+
+/* Like start_preparsed_function, except that instead of a
+ FUNCTION_DECL, this function takes DECLSPECS and DECLARATOR.
+
+ Returns 1 on success. If the DECLARATOR is not suitable for a function
+ (it defines a datum instead), we return 0, which tells
+ yyparse to report a parse error. */
+
+int
+start_function (cp_decl_specifier_seq *declspecs,
+ const cp_declarator *declarator,
+ tree attrs)
+{
+ tree decl1;
+
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+ /* If the declarator is not suitable for a function definition,
+ cause a syntax error. */
+ if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
+ return 0;
+
+ if (DECL_MAIN_P (decl1))
+ /* main must return int. grokfndecl should have corrected it
+ (and issued a diagnostic) if the user got it wrong. */
+ gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)),
+ integer_type_node));
+
+ start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
return 1;
}
+/* Returns true iff an EH_SPEC_BLOCK should be created in the body of
+ FN. */
+
+static bool
+use_eh_spec_block (tree fn)
+{
+ return (flag_exceptions && flag_enforce_eh_specs
+ && !processing_template_decl
+ && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))
+ /* We insert the EH_SPEC_BLOCK only in the original
+ function; then, it is copied automatically to the
+ clones. */
+ && !DECL_CLONED_FUNCTION_P (fn)
+ /* Implicitly-generated constructors and destructors have
+ exception specifications. However, those specifications
+ are the union of the possible exceptions specified by the
+ constructors/destructors for bases and members, so no
+ unallowed exception will ever reach this function. By
+ not creating the EH_SPEC_BLOCK we save a little memory,
+ and we avoid spurious warnings about unreachable
+ code. */
+ && !DECL_ARTIFICIAL (fn));
+}
+
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
digesting the body of the function.
@@ -10574,7 +10874,7 @@ store_parm_decls (tree current_function_parms)
|| TREE_CODE (parm) != VOID_TYPE)
pushdecl (parm);
else
- error ("parameter `%D' declared void", parm);
+ error ("parameter %qD declared void", parm);
}
else
{
@@ -10599,10 +10899,7 @@ store_parm_decls (tree current_function_parms)
DECL_ARGUMENTS is not modified. */
current_binding_level->names = chainon (nonparms, DECL_ARGUMENTS (fndecl));
- /* Do the starting of the exception specifications, if we have any. */
- if (flag_exceptions && !processing_template_decl
- && flag_enforce_eh_specs
- && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
+ if (use_eh_spec_block (current_function_decl))
current_eh_spec_block = begin_eh_spec_block ();
}
@@ -10618,47 +10915,40 @@ save_function_data (tree decl)
/* Save the language-specific per-function data so that we can
get it back when we really expand this function. */
- my_friendly_assert (!DECL_PENDING_INLINE_P (decl),
- 19990908);
+ gcc_assert (!DECL_PENDING_INLINE_P (decl));
/* Make a copy. */
- f = ggc_alloc (sizeof (struct language_function));
+ f = GGC_NEW (struct language_function);
memcpy (f, cp_function_chain, sizeof (struct language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
/* Clear out the bits we don't need. */
- f->base.x_stmt_tree.x_last_stmt = NULL_TREE;
- f->base.x_stmt_tree.x_last_expr_type = NULL_TREE;
- f->x_named_label_uses = NULL;
+ f->base.x_stmt_tree.x_cur_stmt_list = NULL_TREE;
f->bindings = NULL;
f->x_local_names = NULL;
-
- /* If we've already decided that we cannot inline this function, we
- must remember that fact when we actually go to expand the
- function. */
- if (current_function_cannot_inline)
- {
- f->cannot_inline = current_function_cannot_inline;
- DECL_INLINE (decl) = 0;
- }
}
-/* Add a note to mark the beginning of the main body of the constructor.
- This is used to set up the data structures for the cleanup regions for
- fully-constructed bases and members. */
-static void
-begin_constructor_body (void)
-{
-}
-
-/* Add a note to mark the end of the main body of the constructor. This is
- used to end the cleanup regions for fully-constructed bases and
- members. */
+/* Set the return value of the constructor (if present). */
static void
finish_constructor_body (void)
{
+ tree val;
+ tree exprstmt;
+
+ if (targetm.cxx.cdtor_returns_this ())
+ {
+ /* Any return from a constructor will end up here. */
+ add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
+
+ val = DECL_ARGUMENTS (current_function_decl);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (val),
+ DECL_RESULT (current_function_decl), val);
+ /* Return the address of the object. */
+ exprstmt = build_stmt (RETURN_EXPR, val);
+ add_stmt (exprstmt);
+ }
}
/* Do all the processing for the beginning of a destructor; set up the
@@ -10667,45 +10957,25 @@ finish_constructor_body (void)
static void
begin_destructor_body (void)
{
- tree if_stmt;
tree compound_stmt;
- /* If the dtor is empty, and we know there is not any possible
- way we could use any vtable entries, before they are possibly
- set by a base class dtor, we don't have to setup the vtables,
- as we know that any base class dtor will set up any vtables
- it needs. We avoid MI, because one base class dtor can do a
- virtual dispatch to an overridden function that would need to
- have a non-related vtable set up, we cannot avoid setting up
- vtables in that case. We could change this to see if there
- is just one vtable.
-
- ??? In the destructor for a class, the vtables are set
- appropriately for that class. There will be no non-related
- vtables. jason 2001-12-11. */
- if_stmt = begin_if_stmt ();
-
- /* If it is not safe to avoid setting up the vtables, then
- someone will change the condition to be boolean_true_node.
- (Actually, for now, we do not have code to set the condition
- appropriately, so we just assume that we always need to
- initialize the vtables.) */
- finish_if_stmt_cond (boolean_true_node, if_stmt);
-
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
-
- /* Make all virtual function table pointers in non-virtual base
- classes point to CURRENT_CLASS_TYPE's virtual function
- tables. */
- initialize_vtbl_ptrs (current_class_ptr);
-
- finish_compound_stmt (compound_stmt);
- finish_then_clause (if_stmt);
- finish_if_stmt ();
+ /* If the CURRENT_CLASS_TYPE is incomplete, we will have already
+ issued an error message. We still want to try to process the
+ body of the function, but initialize_vtbl_ptrs will crash if
+ TYPE_BINFO is NULL. */
+ if (COMPLETE_TYPE_P (current_class_type))
+ {
+ compound_stmt = begin_compound_stmt (0);
+ /* Make all virtual function table pointers in non-virtual base
+ classes point to CURRENT_CLASS_TYPE's virtual function
+ tables. */
+ initialize_vtbl_ptrs (current_class_ptr);
+ finish_compound_stmt (compound_stmt);
- /* And insert cleanups for our bases and members so that they
- will be properly destroyed if we throw. */
- push_base_cleanups ();
+ /* And insert cleanups for our bases and members so that they
+ will be properly destroyed if we throw. */
+ push_base_cleanups ();
+ }
}
/* At the end of every destructor we generate code to delete the object if
@@ -10718,7 +10988,7 @@ finish_destructor_body (void)
/* Any return from a destructor will end up here; that way all base
and member cleanups will be run when the function returns. */
- add_stmt (build_stmt (LABEL_STMT, dtor_label));
+ add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
/* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl))
@@ -10732,32 +11002,48 @@ finish_destructor_body (void)
an implicit definition), non-placement operator delete shall
be looked up in the scope of the destructor's class and if
found shall be accessible and unambiguous. */
- exprstmt = build_op_delete_call
- (DELETE_EXPR, current_class_ptr, virtual_size,
- LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
+ exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr,
+ virtual_size,
+ /*global_p=*/false,
+ /*placement=*/NULL_TREE,
+ /*alloc_fn=*/NULL_TREE);
if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
- current_in_charge_parm,
- integer_one_node),
+ finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node,
+ current_in_charge_parm,
+ integer_one_node),
if_stmt);
finish_expr_stmt (exprstmt);
finish_then_clause (if_stmt);
- finish_if_stmt ();
+ finish_if_stmt (if_stmt);
+ }
+
+ if (targetm.cxx.cdtor_returns_this ())
+ {
+ tree val;
+
+ val = DECL_ARGUMENTS (current_function_decl);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (val),
+ DECL_RESULT (current_function_decl), val);
+ /* Return the address of the object. */
+ exprstmt = build_stmt (RETURN_EXPR, val);
+ add_stmt (exprstmt);
}
}
/* Do the necessary processing for the beginning of a function body, which
in this case includes member-initializers, but not the catch clauses of
a function-try-block. Currently, this means opening a binding level
- for the member-initializers (in a ctor) and member cleanups (in a dtor).
- In other functions, this isn't necessary, but it doesn't hurt. */
+ for the member-initializers (in a ctor) and member cleanups (in a dtor). */
tree
begin_function_body (void)
{
tree stmt;
+ if (! FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
+ return NULL_TREE;
+
if (processing_template_decl)
/* Do nothing now. */;
else
@@ -10766,13 +11052,10 @@ begin_function_body (void)
operation of dwarfout.c. */
keep_next_level (true);
- stmt = begin_compound_stmt (/*has_no_scope=*/false);
- COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
+ stmt = begin_compound_stmt (BCS_FN_BODY);
if (processing_template_decl)
/* Do nothing now. */;
- else if (DECL_CONSTRUCTOR_P (current_function_decl))
- begin_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl))
begin_destructor_body ();
@@ -10791,6 +11074,9 @@ begin_function_body (void)
void
finish_function_body (tree compstmt)
{
+ if (compstmt == NULL_TREE)
+ return;
+
/* Close the block. */
finish_compound_stmt (compstmt);
@@ -10800,7 +11086,21 @@ finish_function_body (tree compstmt)
finish_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl))
finish_destructor_body ();
-}
+}
+
+/* Given a function, returns the BLOCK corresponding to the outermost level
+ of curly braces, skipping the artificial block created for constructor
+ initializers. */
+
+static tree
+outer_curly_brace_block (tree fndecl)
+{
+ tree block = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl));
+ if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
+ /* Skip the artificial function body block. */
+ block = BLOCK_SUBBLOCKS (block);
+ return block;
+}
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
@@ -10841,58 +11141,66 @@ finish_function (int flags)
This caused &foo to be of type ptr-to-const-function
which then got a warning when stored in a ptr-to-function variable. */
- my_friendly_assert (building_stmt_tree (), 20000911);
-
+ gcc_assert (building_stmt_tree ());
+
/* For a cloned function, we've already got all the code we need;
there's no need to add any extra bits. */
if (!DECL_CLONED_FUNCTION_P (fndecl))
{
if (DECL_MAIN_P (current_function_decl))
{
- /* Make it so that `main' always returns 0 by default. */
+ tree stmt;
+
+ /* Make it so that `main' always returns 0 by default (or
+ 1 for VMS). */
#if VMS_TARGET
- finish_return_stmt (integer_one_node);
+ stmt = finish_return_stmt (integer_one_node);
+#else
+ stmt = finish_return_stmt (integer_zero_node);
+#endif
+ /* Hack. We don't want the middle-end to warn that this
+ return is unreachable, so put the statement on the
+ special line 0. */
+#ifdef USE_MAPPED_LOCATION
+ SET_EXPR_LOCATION (stmt, UNKNOWN_LOCATION);
#else
- finish_return_stmt (integer_zero_node);
+ annotate_with_file_line (stmt, input_filename, 0);
#endif
}
- /* Finish dealing with exception specifiers. */
- if (flag_exceptions && !processing_template_decl
- && flag_enforce_eh_specs
- && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
+ if (use_eh_spec_block (current_function_decl))
finish_eh_spec_block (TYPE_RAISES_EXCEPTIONS
(TREE_TYPE (current_function_decl)),
current_eh_spec_block);
}
- finish_fname_decls ();
-
/* If we're saving up tree structure, tie off the function now. */
- finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
+
+ finish_fname_decls ();
/* If this function can't throw any exceptions, remember that. */
if (!processing_template_decl
&& !cp_function_chain->can_throw
- && !flag_non_call_exceptions)
+ && !flag_non_call_exceptions
+ && !DECL_REPLACEABLE_P (fndecl))
TREE_NOTHROW (fndecl) = 1;
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
this function's blocks. */
-
+
/* If the current binding level isn't the outermost binding level
for this function, either there is a bug, or we have experienced
syntax errors and the statement tree is malformed. */
if (current_binding_level->kind != sk_function_parms)
{
/* Make sure we have already experienced errors. */
- if (errorcount == 0)
- abort ();
+ gcc_assert (errorcount);
/* Throw away the broken statement tree and extra binding
- levels. */
- DECL_SAVED_TREE (fndecl) = build_stmt (COMPOUND_STMT, NULL_TREE);
+ levels. */
+ DECL_SAVED_TREE (fndecl) = alloc_stmt_list ();
while (current_binding_level->kind != sk_function_parms)
{
@@ -10906,12 +11214,10 @@ finish_function (int flags)
/* Statements should always be full-expressions at the outermost set
of curly braces for a function. */
- my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
+ gcc_assert (stmts_are_full_exprs_p ());
- /* Set up the named return value optimization, if we can. Here, we
- eliminate the copy from the nrv into the RESULT_DECL and any cleanup
- for the nrv. genrtl_start_function and declare_return_variable
- handle making the nrv and RESULT_DECL share space. */
+ /* Set up the named return value optimization, if we can. Candidate
+ variables are selected in check_return_value. */
if (current_function_return_value)
{
tree r = current_function_return_value;
@@ -10925,19 +11231,11 @@ finish_function (int flags)
the function so we know that their lifetime always ends with a
return; see g++.dg/opt/nrv6.C. We could be more flexible if
we were to do this optimization in tree-ssa. */
- /* Skip the artificial function body block. */
- && (outer = BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))),
- chain_member (r, BLOCK_VARS (outer))))
- {
-
- DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
- walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
- nullify_returns_r, r);
- }
- else
- /* Clear it so genrtl_start_function and declare_return_variable
- know we're not optimizing. */
- current_function_return_value = NULL_TREE;
+ && (outer = outer_curly_brace_block (fndecl))
+ && chain_member (r, BLOCK_VARS (outer)))
+ finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
+
+ current_function_return_value = NULL_TREE;
}
/* Remember that we were in class scope. */
@@ -10955,18 +11253,6 @@ finish_function (int flags)
if (!processing_template_decl)
save_function_data (fndecl);
- /* If this function calls `setjmp' it cannot be inlined. When
- `longjmp' is called it is not guaranteed to restore the value of
- local variables that have been modified since the call to
- `setjmp'. So, if were to inline this function into some caller
- `c', then when we `longjmp', we might not restore all variables
- in `c'. (It might seem, at first blush, that there's no way for
- this function to modify local variables in `c', but their
- addresses may have been stored somewhere accessible to this
- function.) */
- if (!processing_template_decl && calls_setjmp_p (fndecl))
- DECL_UNINLINABLE (fndecl) = 1;
-
/* Complain if there's just no return statement. */
if (warn_return_type
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
@@ -10977,11 +11263,39 @@ finish_function (int flags)
&& !DECL_NAME (DECL_RESULT (fndecl))
/* Normally, with -Wreturn-type, flow will complain. Unless we're an
inline function, as we might never be compiled separately. */
- && (DECL_INLINE (fndecl) || processing_template_decl))
- warning ("no return statement in function returning non-void");
+ && (DECL_INLINE (fndecl) || processing_template_decl)
+ /* Structor return values (if any) are set by the compiler. */
+ && !DECL_CONSTRUCTOR_P (fndecl)
+ && !DECL_DESTRUCTOR_P (fndecl))
+ warning (OPT_Wreturn_type, "no return statement in function returning non-void");
+
+ /* Store the end of the function, so that we get good line number
+ info for the epilogue. */
+ cfun->function_end_locus = input_location;
+
+ /* Genericize before inlining. */
+ if (!processing_template_decl)
+ {
+ struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
+ cp_genericize (fndecl);
+ /* Clear out the bits we don't need. */
+ f->x_current_class_ptr = NULL;
+ f->x_current_class_ref = NULL;
+ f->x_eh_spec_block = NULL;
+ f->x_in_charge_parm = NULL;
+ f->x_vtt_parm = NULL;
+ f->x_return_value = NULL;
+ f->bindings = NULL;
+ f->extern_decl_map = NULL;
+
+ /* Handle attribute((warn_unused_result)). Relies on gimple input. */
+ c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
+ }
+ /* Clear out the bits we don't need. */
+ local_names = NULL;
/* We're leaving the context of this function, so zap cfun. It's still in
- DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation. */
+ DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation. */
cfun = NULL;
current_function_decl = NULL;
@@ -11030,7 +11344,8 @@ finish_function (int flags)
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (tree declspecs, tree declarator, tree attrlist)
+start_method (cp_decl_specifier_seq *declspecs,
+ const cp_declarator *declarator, tree attrlist)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
&attrlist);
@@ -11053,14 +11368,11 @@ start_method (tree declspecs, tree declarator, tree attrlist)
if (DECL_IN_AGGR_P (fndecl))
{
- if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type)
- {
- if (DECL_CONTEXT (fndecl)
- && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
- error ("`%D' is already defined in class `%T'", fndecl,
- DECL_CONTEXT (fndecl));
- }
- return void_type_node;
+ if (DECL_CONTEXT (fndecl)
+ && TREE_CODE (DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
+ error ("%qD is already defined in class %qT", fndecl,
+ DECL_CONTEXT (fndecl));
+ return error_mark_node;
}
check_template_shadow (fndecl);
@@ -11084,10 +11396,9 @@ start_method (tree declspecs, tree declarator, tree attrlist)
fndecl = copy_node (fndecl);
TREE_CHAIN (fndecl) = NULL_TREE;
}
- grok_special_member_properties (fndecl);
}
- cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
+ finish_decl (fndecl, NULL_TREE, NULL_TREE);
/* Make a place for the parms. */
begin_scope (sk_function_parms, fndecl);
@@ -11135,7 +11446,7 @@ finish_method (tree decl)
{
if (DECL_NAME (link) != NULL_TREE)
pop_binding (DECL_NAME (link), link);
- my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
+ gcc_assert (TREE_CODE (link) != FUNCTION_DECL);
DECL_CONTEXT (link) = NULL_TREE;
}
@@ -11148,8 +11459,8 @@ finish_method (tree decl)
for String.cc in libg++. */
if (DECL_FRIEND_P (fndecl))
{
- CLASSTYPE_INLINE_FRIENDS (current_class_type)
- = tree_cons (NULL_TREE, fndecl, CLASSTYPE_INLINE_FRIENDS (current_class_type));
+ VEC_safe_push (tree, gc, CLASSTYPE_INLINE_FRIENDS (current_class_type),
+ fndecl);
decl = void_type_node;
}
@@ -11163,18 +11474,18 @@ finish_method (tree decl)
void
maybe_register_incomplete_var (tree var)
{
- my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
+ gcc_assert (TREE_CODE (var) == VAR_DECL);
/* Keep track of variables with incomplete types. */
- if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
+ if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
&& DECL_EXTERNAL (var))
{
tree inner_type = TREE_TYPE (var);
-
+
while (TREE_CODE (inner_type) == ARRAY_TYPE)
inner_type = TREE_TYPE (inner_type);
inner_type = TYPE_MAIN_VARIANT (inner_type);
-
+
if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type))
/* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (inner_type)
@@ -11192,21 +11503,26 @@ complete_vars (tree type)
{
tree *list = &incomplete_vars;
- my_friendly_assert (CLASS_TYPE_P (type), 20020406);
- while (*list)
+ gcc_assert (CLASS_TYPE_P (type));
+ while (*list)
{
if (same_type_p (type, TREE_PURPOSE (*list)))
{
tree var = TREE_VALUE (*list);
+ tree type = TREE_TYPE (var);
/* Complete the type of the variable. The VAR_DECL itself
will be laid out in expand_expr. */
- complete_type (TREE_TYPE (var));
+ complete_type (type);
+ cp_apply_type_quals_to_decl (cp_type_quals (type), var);
/* Remove this entry from the list. */
*list = TREE_CHAIN (*list);
}
else
list = &TREE_CHAIN (*list);
}
+
+ /* Check for pending declarations which may have abstract type. */
+ complete_type_check_abstract (type);
}
/* If DECL is of a type which needs a cleanup, build that cleanup
@@ -11221,6 +11537,8 @@ cxx_maybe_build_cleanup (tree decl)
{
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
+ bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
+ && CLASSTYPE_VBASECLASSES (type));
if (TREE_CODE (type) == ARRAY_TYPE)
rval = decl;
@@ -11231,17 +11549,12 @@ cxx_maybe_build_cleanup (tree decl)
}
/* Optimize for space over speed here. */
- if (! TYPE_USES_VIRTUAL_BASECLASSES (type)
- || flag_expensive_optimizations)
+ if (!has_vbases || flag_expensive_optimizations)
flags |= LOOKUP_NONVIRTUAL;
rval = build_delete (TREE_TYPE (rval), rval,
sfk_complete_destructor, flags, 0);
- if (TYPE_USES_VIRTUAL_BASECLASSES (type)
- && ! TYPE_HAS_DESTRUCTOR (type))
- rval = build_compound_expr (rval, build_vbase_delete (type, decl));
-
return rval;
}
return NULL_TREE;
@@ -11252,10 +11565,6 @@ cxx_maybe_build_cleanup (tree decl)
void
finish_stmt (void)
{
- /* Always assume this statement was not an expression statement. If
- it actually was an expression statement, its our callers
- responsibility to fix this up. */
- last_expr_type = NULL_TREE;
}
/* DECL was originally constructed as a non-static member function,
@@ -11270,8 +11579,7 @@ revert_static_member_fn (tree decl)
if (cp_type_quals (TREE_TYPE (TREE_VALUE (args)))
!= TYPE_UNQUALIFIED)
- error ("static member function `%#D' declared with type qualifiers",
- decl);
+ error ("static member function %q#D declared with type qualifiers", decl);
args = TREE_CHAIN (args);
tmp = build_function_type (TREE_TYPE (function), args);
@@ -11290,8 +11598,7 @@ revert_static_member_fn (tree decl)
void
cxx_push_function_context (struct function * f)
{
- struct language_function *p
- = ggc_alloc_cleared (sizeof (struct language_function));
+ struct language_function *p = GGC_CNEW (struct language_function);
f->language = p;
/* Whenever we start a new function, we destroy temporaries in the
@@ -11308,14 +11615,9 @@ cxx_push_function_context (struct function * f)
now, restore saved state. */
*cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
- /* If we decided that we didn't want to inline this function,
- make sure the back-end knows that. */
- if (!current_function_cannot_inline)
- current_function_cannot_inline = cp_function_chain->cannot_inline;
-
/* We don't need the saved data anymore. Unless this is an inline
function; we need the named return value info for
- cp_copy_res_decl_for_inlining. */
+ declare_return_variable. */
if (! DECL_INLINE (fn))
DECL_SAVED_FUNCTION_DATA (fn) = NULL;
}
@@ -11343,9 +11645,9 @@ cp_tree_node_structure (union lang_tree_node * t)
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
case OVERLOAD: return TS_CP_OVERLOAD;
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
+ case TINST_LEVEL: return TS_CP_TINST_LEVEL;
case PTRMEM_CST: return TS_CP_PTRMEM;
- case BASELINK: return TS_CP_BASELINK;
- case WRAPPER: return TS_CP_WRAPPER;
+ case BASELINK: return TS_CP_BASELINK;
default: return TS_CP_GENERIC;
}
}
@@ -11355,16 +11657,49 @@ tree
build_void_list_node (void)
{
tree t = build_tree_list (NULL_TREE, void_type_node);
- TREE_PARMLIST (t) = 1;
return t;
}
-static int
+bool
cp_missing_noreturn_ok_p (tree decl)
{
/* A missing noreturn is ok for the `main' function. */
return DECL_MAIN_P (decl);
}
+/* Return the COMDAT group into which DECL should be placed. */
+
+const char *
+cxx_comdat_group (tree decl)
+{
+ tree name;
+
+ /* Virtual tables, construction virtual tables, and virtual table
+ tables all go in a single COMDAT group, named after the primary
+ virtual table. */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl))
+ name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl)));
+ /* For all other DECLs, the COMDAT group is the mangled name of the
+ declaration itself. */
+ else
+ {
+ while (DECL_THUNK_P (decl))
+ {
+ /* If TARGET_USE_LOCAL_THUNK_ALIAS_P, use_thunk puts the thunk
+ into the same section as the target function. In that case
+ we must return target's name. */
+ tree target = THUNK_TARGET (decl);
+ if (TARGET_USE_LOCAL_THUNK_ALIAS_P (target)
+ && DECL_SECTION_NAME (target) != NULL
+ && DECL_ONE_ONLY (target))
+ decl = target;
+ else
+ break;
+ }
+ name = DECL_ASSEMBLER_NAME (decl);
+ }
+
+ return IDENTIFIER_POINTER (name);
+}
+
#include "gt-cp-decl.h"
-#include "gtype-cp.h"
diff --git a/contrib/gcc/cp/except.c b/contrib/gcc/cp/except.c
index e61e652..f97ab06 100644
--- a/contrib/gcc/cp/except.c
+++ b/contrib/gcc/cp/except.c
@@ -1,6 +1,6 @@
/* Handle exceptional things in C++.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Michael Tiemann <tiemann@cygnus.com>
Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
initial re-implementation courtesy Tad Hunt.
@@ -19,8 +19,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
@@ -37,6 +37,8 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "tree-inline.h"
+#include "tree-iterator.h"
+#include "target.h"
static void push_eh_cleanup (tree);
static tree prepare_eh_type (tree);
@@ -51,7 +53,6 @@ static tree wrap_cleanups_r (tree *, int *, void *);
static int complete_ptr_ref_or_void_ptr_p (tree, tree);
static bool is_admissible_throw_operand (tree);
static int can_convert_eh (tree, tree);
-static void check_handlers_1 (tree, tree);
static tree cp_protect_cleanup_actions (void);
/* Sets up all the global eh stuff that needs to be initialized at the
@@ -79,6 +80,10 @@ init_exception_processing (void)
eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
? "__gxx_personality_sj0"
: "__gxx_personality_v0");
+ if (targetm.arm_eabi_unwinder)
+ unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
+ else
+ default_init_unwind_resume_libfunc ();
lang_eh_runtime_type = build_eh_type_type;
lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
@@ -95,7 +100,7 @@ cp_protect_cleanup_actions (void)
When the destruction of an object during stack unwinding exits
using an exception ... void terminate(); is called. */
return build_call (terminate_node, NULL_TREE);
-}
+}
static tree
prepare_eh_type (tree type)
@@ -144,13 +149,33 @@ build_eh_type_type (tree type)
mark_used (exp);
- return build1 (ADDR_EXPR, ptr_type_node, exp);
+ return convert (ptr_type_node, build_address (exp));
}
tree
build_exc_ptr (void)
{
- return build (EXC_PTR_EXPR, ptr_type_node);
+ return build0 (EXC_PTR_EXPR, ptr_type_node);
+}
+
+/* Build up a call to __cxa_get_exception_ptr so that we can build a
+ copy constructor for the thrown object. */
+
+static tree
+do_get_exception_ptr (void)
+{
+ tree fn;
+
+ fn = get_identifier ("__cxa_get_exception_ptr");
+ if (!get_global_value_if_present (fn, &fn))
+ {
+ /* Declare void* __cxa_get_exception_ptr (void *). */
+ tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
+ }
+
+ return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
+ NULL_TREE));
}
/* Build up a call to __cxa_begin_catch, to tell the runtime that the
@@ -182,9 +207,12 @@ dtor_nothrow (tree type)
if (type == NULL_TREE)
return 0;
- if (! TYPE_HAS_DESTRUCTOR (type))
+ if (!CLASS_TYPE_P (type))
return 1;
+ if (CLASSTYPE_LAZY_DESTRUCTOR (type))
+ lazily_declare_fn (sfk_destructor, type);
+
return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
}
@@ -236,8 +264,8 @@ decl_is_java_type (tree decl, int err)
&& TYPE_FOR_JAVA (TREE_TYPE (decl)))
{
/* Can't throw a reference. */
- error ("type `%T' is disallowed in Java `throw' or `catch'",
- decl);
+ error ("type %qT is disallowed in Java %<throw%> or %<catch%>",
+ decl);
}
if (r)
@@ -247,15 +275,15 @@ decl_is_java_type (tree decl, int err)
if (jthrow_node == NULL_TREE)
fatal_error
- ("call to Java `catch' or `throw' with `jthrowable' undefined");
+ ("call to Java %<catch%> or %<throw%> with %<jthrowable%> undefined");
jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
{
/* Thrown object must be a Throwable. */
- error ("type `%T' is not derived from `java::lang::Throwable'",
- TREE_TYPE (decl));
+ error ("type %qT is not derived from %<java::lang::Throwable%>",
+ TREE_TYPE (decl));
}
}
}
@@ -312,7 +340,7 @@ choose_personality_routine (enum languages lang)
break;
default:
- abort ();
+ gcc_unreachable ();
}
return;
@@ -323,7 +351,7 @@ choose_personality_routine (enum languages lang)
/* Initialize the catch parameter DECL. */
-static void
+static void
initialize_handler_parm (tree decl, tree exp)
{
tree init;
@@ -334,11 +362,10 @@ initialize_handler_parm (tree decl, tree exp)
TREE_USED (decl) = 1;
/* Figure out the type that the initializer is. Pointers are returned
- adjusted by value from __cxa_begin_catch. Others are returned by
+ adjusted by value from __cxa_begin_catch. Others are returned by
reference. */
init_type = TREE_TYPE (decl);
- if (! TYPE_PTR_P (init_type)
- && TREE_CODE (init_type) != REFERENCE_TYPE)
+ if (!POINTER_TYPE_P (init_type))
init_type = build_reference_type (init_type);
choose_personality_routine (decl_is_java_type (init_type, 0)
@@ -365,12 +392,10 @@ initialize_handler_parm (tree decl, tree exp)
init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
}
- /* Let `cp_finish_decl' know that this initializer is ok. */
- DECL_INITIAL (decl) = error_mark_node;
decl = pushdecl (decl);
- start_decl_1 (decl);
- cp_finish_decl (decl, init, NULL_TREE,
+ start_decl_1 (decl, true);
+ cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
@@ -379,61 +404,73 @@ initialize_handler_parm (tree decl, tree exp)
tree
expand_start_catch_block (tree decl)
{
- tree exp = NULL_TREE;
+ tree exp;
tree type;
- bool is_java;
if (! doing_eh (1))
return NULL_TREE;
/* Make sure this declaration is reasonable. */
if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
- decl = NULL_TREE;
+ decl = error_mark_node;
if (decl)
type = prepare_eh_type (TREE_TYPE (decl));
else
type = NULL_TREE;
- is_java = false;
- if (decl)
+ if (decl && decl_is_java_type (type, 1))
{
- tree init;
-
- if (decl_is_java_type (type, 1))
- {
- /* Java only passes object via pointer and doesn't require
- adjusting. The java object is immediately before the
- generic exception header. */
- init = build_exc_ptr ();
- init = build1 (NOP_EXPR, build_pointer_type (type), init);
- init = build (MINUS_EXPR, TREE_TYPE (init), init,
- TYPE_SIZE_UNIT (TREE_TYPE (init)));
- init = build_indirect_ref (init, NULL);
- is_java = true;
- }
- else
- {
- /* C++ requires that we call __cxa_begin_catch to get the
- pointer to the actual object. */
- init = do_begin_catch ();
- }
-
- exp = create_temporary_var (ptr_type_node);
- DECL_REGISTER (exp) = 1;
- cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
- finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
+ /* Java only passes object via pointer and doesn't require
+ adjusting. The java object is immediately before the
+ generic exception header. */
+ exp = build_exc_ptr ();
+ exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
+ exp = build2 (MINUS_EXPR, TREE_TYPE (exp), exp,
+ TYPE_SIZE_UNIT (TREE_TYPE (exp)));
+ exp = build_indirect_ref (exp, NULL);
+ initialize_handler_parm (decl, exp);
+ return type;
}
- else
+
+ /* Call __cxa_end_catch at the end of processing the exception. */
+ push_eh_cleanup (type);
+
+ /* If there's no decl at all, then all we need to do is make sure
+ to tell the runtime that we've begun handling the exception. */
+ if (decl == NULL || decl == error_mark_node)
finish_expr_stmt (do_begin_catch ());
- /* C++ requires that we call __cxa_end_catch at the end of
- processing the exception. */
- if (! is_java)
- push_eh_cleanup (type);
+ /* If the C++ object needs constructing, we need to do that before
+ calling __cxa_begin_catch, so that std::uncaught_exception gets
+ the right value during the copy constructor. */
+ else if (flag_use_cxa_get_exception_ptr
+ && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ {
+ exp = do_get_exception_ptr ();
+ initialize_handler_parm (decl, exp);
+ finish_expr_stmt (do_begin_catch ());
+ }
- if (decl)
- initialize_handler_parm (decl, exp);
+ /* Otherwise the type uses a bitwise copy, and we don't have to worry
+ about the value of std::uncaught_exception and therefore can do the
+ copy with the return value of __cxa_end_catch instead. */
+ else
+ {
+ tree init = do_begin_catch ();
+ tree init_type = type;
+
+ /* Pointers are passed by values, everything else by reference. */
+ if (!TYPE_PTR_P (type))
+ init_type = build_pointer_type (type);
+ if (init_type != TREE_TYPE (init))
+ init = build1 (NOP_EXPR, init_type, init);
+ exp = create_temporary_var (init_type);
+ DECL_REGISTER (exp) = 1;
+ cp_finish_decl (exp, init, /*init_const_expr=*/false,
+ NULL_TREE, LOOKUP_ONLYCONVERTING);
+ initialize_handler_parm (decl, exp);
+ }
return type;
}
@@ -462,6 +499,7 @@ begin_eh_spec_block (void)
{
tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
add_stmt (r);
+ EH_SPEC_STMTS (r) = push_stmt_list ();
return r;
}
@@ -470,7 +508,7 @@ finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
{
tree raises;
- RECHAIN_STMTS (eh_spec_block, EH_SPEC_STMTS (eh_spec_block));
+ EH_SPEC_STMTS (eh_spec_block) = pop_stmt_list (EH_SPEC_STMTS (eh_spec_block));
/* Strip cv quals, etc, from the specification types. */
for (raises = NULL_TREE;
@@ -501,7 +539,7 @@ do_allocate_exception (tree type)
tree tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
}
-
+
return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type),
NULL_TREE));
}
@@ -530,7 +568,7 @@ do_free_exception (tree ptr)
static tree
wrap_cleanups_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- void *data ATTRIBUTE_UNUSED)
+ void *data ATTRIBUTE_UNUSED)
{
tree exp = *tp;
tree cleanup;
@@ -567,17 +605,18 @@ build_throw (tree exp)
if (processing_template_decl)
{
- current_function_returns_abnormally = 1;
+ if (cfun)
+ current_function_returns_abnormally = 1;
return build_min (THROW_EXPR, void_type_node, exp);
}
if (exp == null_node)
- warning ("throwing NULL, which has integral, not pointer type");
-
+ warning (0, "throwing NULL, which has integral, not pointer type");
+
if (exp != NULL_TREE)
{
if (!is_admissible_throw_operand (exp))
- return error_mark_node;
+ return error_mark_node;
}
if (! doing_eh (1))
@@ -595,7 +634,7 @@ build_throw (tree exp)
}
else if (really_overloaded_fn (fn))
{
- error ("`%D' should never be overloaded", fn);
+ error ("%qD should never be overloaded", fn);
return error_mark_node;
}
fn = OVL_CURRENT (fn);
@@ -604,6 +643,7 @@ build_throw (tree exp)
else if (exp)
{
tree throw_type;
+ tree temp_type;
tree cleanup;
tree object, ptr;
tree tmp;
@@ -618,7 +658,7 @@ build_throw (tree exp)
tmp = build_function_type (void_type_node, tmp);
cleanup_type = build_pointer_type (tmp);
}
-
+
fn = get_identifier ("__cxa_throw");
if (!get_global_value_if_present (fn, &fn))
{
@@ -631,10 +671,18 @@ build_throw (tree exp)
tmp = build_function_type (void_type_node, tmp);
fn = push_throw_library_fn (fn, tmp);
}
-
- /* throw expression */
- /* First, decay it. */
- exp = decay_conversion (exp);
+
+ /* [except.throw]
+
+ A throw-expression initializes a temporary object, the type
+ of which is determined by removing any top-level
+ cv-qualifiers from the static type of the operand of throw
+ and adjusting the type from "array of T" or "function return
+ T" to "pointer to T" or "pointer to function returning T"
+ respectively. */
+ temp_type = is_bitfield_expr_with_lowered_type (exp);
+ if (!temp_type)
+ temp_type = type_decays_to (TYPE_MAIN_VARIANT (TREE_TYPE (exp)));
/* OK, this is kind of wacky. The standard says that we call
terminate when the exception handling mechanism, after
@@ -650,51 +698,70 @@ build_throw (tree exp)
matter, since it can't throw). */
/* Allocate the space for the exception. */
- allocate_expr = do_allocate_exception (TREE_TYPE (exp));
+ allocate_expr = do_allocate_exception (temp_type);
allocate_expr = get_target_expr (allocate_expr);
ptr = TARGET_EXPR_SLOT (allocate_expr);
- object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
+ object = build_nop (build_pointer_type (temp_type), ptr);
object = build_indirect_ref (object, NULL);
elided = (TREE_CODE (exp) == TARGET_EXPR);
/* And initialize the exception object. */
- exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
- if (exp == error_mark_node)
+ if (CLASS_TYPE_P (temp_type))
{
- error (" in thrown expression");
- return error_mark_node;
+ /* Call the copy constructor. */
+ exp = (build_special_member_call
+ (object, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, exp),
+ TREE_TYPE (object),
+ LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING));
+ if (exp == error_mark_node)
+ {
+ error (" in thrown expression");
+ return error_mark_node;
+ }
}
+ else
+ exp = build2 (INIT_EXPR, temp_type, object,
+ decay_conversion (exp));
/* Pre-evaluate the thrown expression first, since if we allocated
the space first we would have to deal with cleaning it up if
evaluating this expression throws.
- The case where EXP the initializer is a call to a constructor or a
- function returning a class is a bit of a grey area in the
- standard; it's unclear whether or not it should be allowed to
- throw. We used to say no, as that allowed us to optimize this
- case without worrying about deallocating the exception object if
- it does. But that conflicted with expectations (PR 13944) and the
- EDG compiler; now we wrap the initialization in a TRY_CATCH_EXPR
- to call do_free_exception rather than in a MUST_NOT_THROW_EXPR,
- for this case only.
-
- Note that we don't check the return value from stabilize_init
- because it will only return false in cases where elided is true,
- and therefore we don't need to work around the failure to
- preevaluate. */
+ The case where EXP the initializer is a cast or a function
+ returning a class is a bit of a grey area in the standard; it's
+ unclear whether or not it should be allowed to throw. We used to
+ say no, as that allowed us to optimize this case without worrying
+ about deallocating the exception object if it does. But that
+ conflicted with expectations (PR 13944) and the EDG compiler; now
+ we wrap the initialization in a TRY_CATCH_EXPR to call
+ do_free_exception rather than in a MUST_NOT_THROW_EXPR, for this
+ case only.
+
+ BUT: Issue 475 may do away with this inconsistency by removing the
+ terminate() in this situation.
+
+ Note that we don't check the return value from stabilize_init
+ because it will only return false in cases where elided is true,
+ and therefore we don't need to work around the failure to
+ preevaluate. */
temp_expr = NULL_TREE;
stabilize_init (exp, &temp_expr);
+ /* Wrap the initialization in a CLEANUP_POINT_EXPR so that cleanups
+ for temporaries within the initialization are run before the one
+ for the exception object, preserving LIFO order. */
+ exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);
+
if (elided)
- exp = build (TRY_CATCH_EXPR, void_type_node, exp,
- do_free_exception (ptr));
+ exp = build2 (TRY_CATCH_EXPR, void_type_node, exp,
+ do_free_exception (ptr));
else
exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
/* Prepend the allocation. */
- exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
+ exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
if (temp_expr)
{
/* Prepend the calculation of the throw expression. Also, force
@@ -703,13 +770,13 @@ build_throw (tree exp)
them in MUST_NOT_THROW_EXPR, since they are run after the
exception object is initialized. */
walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
- exp = build (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
+ exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
}
throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
- if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
{
cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
complete_dtor_identifier, 0);
@@ -720,10 +787,7 @@ build_throw (tree exp)
cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
}
else
- {
- cleanup = build_int_2 (0, 0);
- TREE_TYPE (cleanup) = cleanup_type;
- }
+ cleanup = build_int_cst (cleanup_type, 0);
tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
tmp = tree_cons (NULL_TREE, throw_type, tmp);
@@ -732,7 +796,7 @@ build_throw (tree exp)
tmp = build_function_call (fn, tmp);
/* Tack on the initialization stuff. */
- exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
+ exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
}
else
{
@@ -747,7 +811,7 @@ build_throw (tree exp)
}
/* ??? Indicate that this function call allows exceptions of the type
- of the enclosing catch block (if known). */
+ of the enclosing catch block (if known). */
exp = build_function_call (fn, NULL_TREE);
}
@@ -765,22 +829,22 @@ static int
complete_ptr_ref_or_void_ptr_p (tree type, tree from)
{
int is_ptr;
-
+
/* Check complete. */
type = complete_type_or_else (type, from);
if (!type)
return 0;
-
+
/* Or a pointer or ref to one, or cv void *. */
is_ptr = TREE_CODE (type) == POINTER_TYPE;
if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
{
tree core = TREE_TYPE (type);
-
+
if (is_ptr && VOID_TYPE_P (core))
- /* OK */;
+ /* OK */;
else if (!complete_type_or_else (core, from))
- return 0;
+ return 0;
}
return 1;
}
@@ -795,21 +859,22 @@ is_admissible_throw_operand (tree expr)
tree type = TREE_TYPE (expr);
/* 15.1/4 [...] The type of the throw-expression shall not be an
- incomplete type, or a pointer or a reference to an incomplete
- type, other than void*, const void*, volatile void*, or
- const volatile void*. Except for these restriction and the
- restrictions on type matching mentioned in 15.3, the operand
- of throw is treated exactly as a function argument in a call
- (5.2.2) or the operand of a return statement. */
+ incomplete type, or a pointer or a reference to an incomplete
+ type, other than void*, const void*, volatile void*, or
+ const volatile void*. Except for these restriction and the
+ restrictions on type matching mentioned in 15.3, the operand
+ of throw is treated exactly as a function argument in a call
+ (5.2.2) or the operand of a return statement. */
if (!complete_ptr_ref_or_void_ptr_p (type, expr))
return false;
/* 10.4/3 An abstract class shall not be used as a parameter type,
- as a function return type or as type of an explicit
- conversion. */
+ as a function return type or as type of an explicit
+ conversion. */
else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
{
- error ("expression '%E' of abstract class type '%T' cannot be used in throw-expression", expr, type);
+ error ("expression %qE of abstract class type %qT cannot "
+ "be used in throw-expression", expr, type);
return false;
}
@@ -840,7 +905,10 @@ nothrow_libfn_p (tree fn)
/* Can't be a C library function. */
return 0;
- id = DECL_ASSEMBLER_NAME (fn);
+ /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME
+ unless the system headers are playing rename tricks, and if
+ they are, we don't want to be confused by them. */
+ id = DECL_NAME (fn);
return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
}
@@ -874,51 +942,57 @@ can_convert_eh (tree to, tree from)
return 0;
}
-/* Check whether any of HANDLERS are shadowed by another handler accepting
- TYPE. Note that the shadowing may not be complete; even if an exception
- of type B would be caught by a handler for A, there could be a derived
- class C for which A is an ambiguous base but B is not, so the handler
- for B would catch an exception of type C. */
+/* Check whether any of the handlers in I are shadowed by another handler
+ accepting TYPE. Note that the shadowing may not be complete; even if
+ an exception of type B would be caught by a handler for A, there could
+ be a derived class C for which A is an ambiguous base but B is not, so
+ the handler for B would catch an exception of type C. */
static void
-check_handlers_1 (tree master, tree handlers)
+check_handlers_1 (tree master, tree_stmt_iterator i)
{
tree type = TREE_TYPE (master);
- tree handler;
- for (handler = handlers; handler; handler = TREE_CHAIN (handler))
- if (TREE_TYPE (handler)
- && can_convert_eh (type, TREE_TYPE (handler)))
- {
- input_line = STMT_LINENO (handler);
- warning ("exception of type `%T' will be caught",
- TREE_TYPE (handler));
- input_line = STMT_LINENO (master);
- warning (" by earlier handler for `%T'", type);
- break;
- }
+ for (; !tsi_end_p (i); tsi_next (&i))
+ {
+ tree handler = tsi_stmt (i);
+ if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
+ {
+ warning (0, "%Hexception of type %qT will be caught",
+ EXPR_LOCUS (handler), TREE_TYPE (handler));
+ warning (0, "%H by earlier handler for %qT",
+ EXPR_LOCUS (master), type);
+ break;
+ }
+ }
}
-/* Given a chain of HANDLERs, make sure that they're OK. */
+/* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK. */
void
check_handlers (tree handlers)
{
- tree handler;
- int save_line = input_line;
-
- for (handler = handlers; handler; handler = TREE_CHAIN (handler))
- {
- if (TREE_CHAIN (handler) == NULL_TREE)
- /* No more handlers; nothing to shadow. */;
- else if (TREE_TYPE (handler) == NULL_TREE)
- {
- input_line = STMT_LINENO (handler);
- pedwarn
- ("`...' handler must be the last handler for its try block");
- }
- else
- check_handlers_1 (handler, TREE_CHAIN (handler));
- }
- input_line = save_line;
+ tree_stmt_iterator i;
+
+ /* If we don't have a STATEMENT_LIST, then we've just got one
+ handler, and thus nothing to warn about. */
+ if (TREE_CODE (handlers) != STATEMENT_LIST)
+ return;
+
+ i = tsi_start (handlers);
+ if (!tsi_end_p (i))
+ while (1)
+ {
+ tree handler = tsi_stmt (i);
+ tsi_next (&i);
+
+ /* No more handlers; nothing to shadow. */
+ if (tsi_end_p (i))
+ break;
+ if (TREE_TYPE (handler) == NULL_TREE)
+ pedwarn ("%H%<...%> handler must be the last handler for"
+ " its try block", EXPR_LOCUS (handler));
+ else
+ check_handlers_1 (handler, i);
+ }
}
diff --git a/contrib/gcc/cp/ptree.c b/contrib/gcc/cp/ptree.c
index 057add6..1de4d2c 100644
--- a/contrib/gcc/cp/ptree.c
+++ b/contrib/gcc/cp/ptree.c
@@ -1,6 +1,6 @@
/* Prints out trees in human readable form.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* $FreeBSD$ */
@@ -29,13 +29,6 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "cp-tree.h"
-#ifndef HOST_PTR_PRINTF_FORMAT
-#define HOST_PTR_PRINTF_FORMAT HOST_PTR_PRINTF
-#endif
-#ifndef HOST_PTR_PRINTF_TYPE
-#define HOST_PTR_PRINTF_TYPE (void *)
-#endif
-
void
cxx_print_decl (FILE *file, tree node, int indent)
{
@@ -49,21 +42,22 @@ cxx_print_decl (FILE *file, tree node, int indent)
return;
}
- if (!DECL_LANG_SPECIFIC (node))
+ if (!CODE_CONTAINS_STRUCT (TREE_CODE (node), TS_DECL_COMMON)
+ || !DECL_LANG_SPECIFIC (node))
return;
indent_to (file, indent + 3);
if (TREE_CODE (node) == FUNCTION_DECL
&& DECL_PENDING_INLINE_INFO (node))
- fprintf (file, " pending-inline-info " HOST_PTR_PRINTF_FORMAT,
- HOST_PTR_PRINTF_TYPE DECL_PENDING_INLINE_INFO (node));
+ fprintf (file, " pending-inline-info %p",
+ (void *) DECL_PENDING_INLINE_INFO (node));
if (TREE_CODE (node) == TYPE_DECL
&& DECL_SORTED_FIELDS (node))
- fprintf (file, " sorted-fields " HOST_PTR_PRINTF_FORMAT,
- HOST_PTR_PRINTF_TYPE DECL_SORTED_FIELDS (node));
+ fprintf (file, " sorted-fields %p",
+ (void *) DECL_SORTED_FIELDS (node));
if ((TREE_CODE (node) == FUNCTION_DECL || TREE_CODE (node) == VAR_DECL)
&& DECL_TEMPLATE_INFO (node))
- fprintf (file, " template-info " HOST_PTR_PRINTF_FORMAT,
- HOST_PTR_PRINTF_TYPE DECL_TEMPLATE_INFO (node));
+ fprintf (file, " template-info %p",
+ (void *) DECL_TEMPLATE_INFO (node));
}
void
@@ -108,8 +102,6 @@ cxx_print_type (FILE *file, tree node, int indent)
fputs ( "needs-constructor", file);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
fputs (" needs-destructor", file);
- if (TYPE_HAS_DESTRUCTOR (node))
- fputs (" ~X()", file);
if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node))
fputs (" X()", file);
if (TYPE_HAS_CONVERSION (node))
@@ -131,19 +123,20 @@ cxx_print_type (FILE *file, tree node, int indent)
fputs (" delete[]", file);
if (TYPE_HAS_ASSIGN_REF (node))
fputs (" this=(X&)", file);
- if (TYPE_USES_MULTIPLE_INHERITANCE (node))
- fputs (" uses-multiple-inheritance", file);
if (TREE_CODE (node) == RECORD_TYPE)
{
- fprintf (file, " n_parents %d", CLASSTYPE_N_BASECLASSES (node));
+ if (TYPE_BINFO (node))
+ fprintf (file, " n_parents=%d",
+ BINFO_N_BASE_BINFOS (TYPE_BINFO (node)));
+ else
+ fprintf (file, " no-binfo");
+
fprintf (file, " use_template=%d", CLASSTYPE_USE_TEMPLATE (node));
if (CLASSTYPE_INTERFACE_ONLY (node))
fprintf (file, " interface-only");
if (CLASSTYPE_INTERFACE_UNKNOWN (node))
fprintf (file, " interface-unknown");
- print_node (file, "member-functions", CLASSTYPE_METHOD_VEC (node),
- indent + 4);
}
}
@@ -151,22 +144,25 @@ cxx_print_type (FILE *file, tree node, int indent)
static void
cxx_print_binding (FILE *stream, cxx_binding *binding, const char *prefix)
{
- fprintf (stream, "%s <" HOST_PTR_PRINTF_FORMAT ">",
- prefix, HOST_PTR_PRINTF_TYPE binding);
+ fprintf (stream, "%s <%p>",
+ prefix, (void *) binding);
}
void
cxx_print_identifier (FILE *file, tree node, int indent)
{
- indent_to (file, indent);
+ if (indent == 0)
+ fprintf (file, " ");
+ else
+ indent_to (file, indent);
cxx_print_binding (file, IDENTIFIER_NAMESPACE_BINDINGS (node), "bindings");
- print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
- indent_to (file, indent);
+ if (indent == 0)
+ fprintf (file, " ");
+ else
+ indent_to (file, indent);
cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings");
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
- print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
- print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
}
void
@@ -174,6 +170,12 @@ cxx_print_xnode (FILE *file, tree node, int indent)
{
switch (TREE_CODE (node))
{
+ case BASELINK:
+ print_node (file, "functions", BASELINK_FUNCTIONS (node), indent + 4);
+ print_node (file, "binfo", BASELINK_BINFO (node), indent + 4);
+ print_node (file, "access_binfo", BASELINK_ACCESS_BINFO (node),
+ indent + 4);
+ break;
case OVERLOAD:
print_node (file, "function", OVL_FUNCTION (node), indent+4);
print_node (file, "chain", TREE_CHAIN (node), indent+4);
diff --git a/contrib/gcc/dbxout.c b/contrib/gcc/dbxout.c
index b12ea5c..5732427 100644
--- a/contrib/gcc/dbxout.c
+++ b/contrib/gcc/dbxout.c
@@ -1,6 +1,7 @@
/* Output dbx-format symbol table information from GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* Output dbx-format symbol table data.
@@ -79,7 +80,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "regs.h"
#include "insn-config.h"
#include "reload.h"
-#include "output.h" /* ASM_OUTPUT_SOURCE_LINE may refer to sdb functions. */
+#include "output.h"
#include "dbxout.h"
#include "toplev.h"
#include "tm_p.h"
@@ -88,28 +89,36 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "function.h"
#include "target.h"
#include "langhooks.h"
+#include "obstack.h"
+#include "expr.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h"
#endif
-#undef DBXOUT_DECR_NESTING
#define DBXOUT_DECR_NESTING \
if (--debug_nesting == 0 && symbol_queue_index > 0) \
{ emit_pending_bincls_if_required (); debug_flush_symbol_queue (); }
-#undef DBXOUT_DECR_NESTING_AND_RETURN
#define DBXOUT_DECR_NESTING_AND_RETURN(x) \
do {--debug_nesting; return (x);} while (0)
#ifndef ASM_STABS_OP
-#define ASM_STABS_OP "\t.stabs\t"
+# ifdef XCOFF_DEBUGGING_INFO
+# define ASM_STABS_OP "\t.stabx\t"
+# else
+# define ASM_STABS_OP "\t.stabs\t"
+# endif
#endif
#ifndef ASM_STABN_OP
#define ASM_STABN_OP "\t.stabn\t"
#endif
+#ifndef ASM_STABD_OP
+#define ASM_STABD_OP "\t.stabd\t"
+#endif
+
#ifndef DBX_TYPE_DECL_STABS_CODE
#define DBX_TYPE_DECL_STABS_CODE N_LSYM
#endif
@@ -126,24 +135,32 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define DBX_REGPARM_STABS_LETTER 'P'
#endif
-/* This is used for parameters passed by invisible reference in a register. */
-#ifndef GDB_INV_REF_REGPARM_STABS_LETTER
-#define GDB_INV_REF_REGPARM_STABS_LETTER 'a'
+#ifndef NO_DBX_FUNCTION_END
+#define NO_DBX_FUNCTION_END 0
#endif
-#ifndef DBX_MEMPARM_STABS_LETTER
-#define DBX_MEMPARM_STABS_LETTER 'p'
+#ifndef NO_DBX_BNSYM_ENSYM
+#define NO_DBX_BNSYM_ENSYM 0
#endif
-#ifndef FILE_NAME_JOINER
-#define FILE_NAME_JOINER "/"
+#ifndef NO_DBX_MAIN_SOURCE_DIRECTORY
+#define NO_DBX_MAIN_SOURCE_DIRECTORY 0
+#endif
+
+#ifndef DBX_BLOCKS_FUNCTION_RELATIVE
+#define DBX_BLOCKS_FUNCTION_RELATIVE 0
+#endif
+
+#ifndef DBX_LINES_FUNCTION_RELATIVE
+#define DBX_LINES_FUNCTION_RELATIVE 0
+#endif
+
+#ifndef DBX_CONTIN_LENGTH
+#define DBX_CONTIN_LENGTH 80
#endif
-/* GDB needs to know that the stabs were generated by GCC. We emit an
- N_OPT stab at the beginning of the source file to indicate this.
- The string is historical, and different on a very few targets. */
-#ifndef STABS_GCC_MARKER
-#define STABS_GCC_MARKER "gcc2_compiled."
+#ifndef DBX_CONTIN_CHAR
+#define DBX_CONTIN_CHAR '\\'
#endif
enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
@@ -179,6 +196,12 @@ static GTY(()) int typevec_len;
static GTY(()) int next_type_number;
+/* The C front end may call dbxout_symbol before dbxout_init runs.
+ We save all such decls in this list and output them when we get
+ to dbxout_init. */
+
+static GTY(()) tree preinit_symbols;
+
enum binclstatus {BINCL_NOT_REQUIRED, BINCL_PENDING, BINCL_PROCESSED};
/* When using N_BINCL in dbx output, each type number is actually a
@@ -220,13 +243,6 @@ static GTY(()) int scope_labelno;
static GTY(()) int dbxout_source_line_counter;
-/* Nonzero if we have actually used any of the GDB extensions
- to the debugging format. The idea is that we use them for the
- first time only if there's a strong reason, but once we have done that,
- we use them whenever convenient. */
-
-static GTY(()) int have_used_extensions = 0;
-
/* Number for the next N_SOL filename stabs label. The number 0 is reserved
for the N_SO filename stabs label. */
@@ -253,12 +269,8 @@ static int pending_bincls = 0;
/* The original input file name. */
static const char *base_input_file;
-/* Current working directory. */
-
-static const char *cwd;
-
#ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT function_section (current_function_decl);
+#define FORCE_TEXT switch_to_section (current_function_section ())
#else
#define FORCE_TEXT
#endif
@@ -270,7 +282,7 @@ static const char *cwd;
/* 1 if PARM is passed to this function in memory. */
#define PARM_PASSED_IN_MEMORY(PARM) \
- (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
+ (MEM_P (DECL_INCOMING_RTL (PARM)))
/* A C expression for the integer offset value of an automatic variable
(N_LSYM) having address X (an RTX). */
@@ -285,46 +297,11 @@ static const char *cwd;
#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
#endif
-/* Stream for writing to assembler file. */
-
-static FILE *asmfile;
-
-/* These variables are for dbxout_symbol to communicate to
- dbxout_finish_symbol.
- current_sym_code is the symbol-type-code, a symbol N_... define in stab.h.
- current_sym_value and current_sym_addr are two ways to address the
- value to store in the symtab entry.
- current_sym_addr if nonzero represents the value as an rtx.
- If that is zero, current_sym_value is used. This is used
- when the value is an offset (such as for auto variables,
- register variables and parms). */
-
-static STAB_CODE_TYPE current_sym_code;
-static int current_sym_value;
-static rtx current_sym_addr;
-
-/* Number of chars of symbol-description generated so far for the
- current symbol. Used by CHARS and CONTIN. */
-
-static int current_sym_nchars;
-
-/* Report having output N chars of the current symbol-description. */
-
-#define CHARS(N) (current_sym_nchars += (N))
-
-/* Break the current symbol-description, generating a continuation,
- if it has become long. */
-
-#ifndef DBX_CONTIN_LENGTH
-#define DBX_CONTIN_LENGTH 80
-#endif
-
-#if DBX_CONTIN_LENGTH > 0
-#define CONTIN \
- do {if (current_sym_nchars > DBX_CONTIN_LENGTH) dbxout_continue ();} while (0)
-#else
-#define CONTIN do { } while (0)
-#endif
+/* This obstack holds the stab string currently being constructed. We
+ build it up here, then write it out, so we can split long lines up
+ properly (see dbxout_finish_complex_stabs). */
+static struct obstack stabstr_ob;
+static size_t stabstr_last_contin_point;
#ifdef DBX_USE_BINCL
static void emit_bincl_stab (const char *c);
@@ -333,40 +310,35 @@ static void emit_pending_bincls (void);
static inline void emit_pending_bincls_if_required (void);
static void dbxout_init (const char *);
+
static void dbxout_finish (const char *);
static void dbxout_start_source_file (unsigned, const char *);
static void dbxout_end_source_file (unsigned);
static void dbxout_typedefs (tree);
static void dbxout_type_index (tree);
-#if DBX_CONTIN_LENGTH > 0
-static void dbxout_continue (void);
-#endif
static void dbxout_args (tree);
static void dbxout_type_fields (tree);
-static void dbxout_type_method_1 (tree, const char *);
+static void dbxout_type_method_1 (tree);
static void dbxout_type_methods (tree);
static void dbxout_range_type (tree);
static void dbxout_type (tree, int);
static bool print_int_cst_bounds_in_octal_p (tree);
-static void print_int_cst_octal (tree);
-static void print_octal (unsigned HOST_WIDE_INT, int);
-static void print_wide_int (HOST_WIDE_INT);
static void dbxout_type_name (tree);
static void dbxout_class_name_qualifiers (tree);
static int dbxout_symbol_location (tree, tree, const char *, rtx);
static void dbxout_symbol_name (tree, const char *, int);
-static void dbxout_prepare_symbol (tree);
-static void dbxout_finish_symbol (tree);
static void dbxout_block (tree, int, tree);
static void dbxout_global_decl (tree);
+static void dbxout_type_decl (tree, int);
static void dbxout_handle_pch (unsigned);
/* The debug hooks structure. */
#if defined (DBX_DEBUGGING_INFO)
static void dbxout_source_line (unsigned int, const char *);
-static void dbxout_source_file (FILE *, const char *);
-static void dbxout_function_end (void);
+static void dbxout_begin_prologue (unsigned int, const char *);
+static void dbxout_source_file (const char *);
+static void dbxout_function_end (tree);
static void dbxout_begin_function (tree);
static void dbxout_begin_block (unsigned, unsigned);
static void dbxout_end_block (unsigned, unsigned);
@@ -382,23 +354,28 @@ const struct gcc_debug_hooks dbx_debug_hooks =
dbxout_end_source_file,
dbxout_begin_block,
dbxout_end_block,
- debug_true_tree, /* ignore_block */
- dbxout_source_line, /* source_line */
- dbxout_source_line, /* begin_prologue: just output line info */
- debug_nothing_int_charstar, /* end_prologue */
- debug_nothing_int_charstar, /* end_epilogue */
+ debug_true_tree, /* ignore_block */
+ dbxout_source_line, /* source_line */
+ dbxout_begin_prologue, /* begin_prologue */
+ debug_nothing_int_charstar, /* end_prologue */
+ debug_nothing_int_charstar, /* end_epilogue */
#ifdef DBX_FUNCTION_FIRST
dbxout_begin_function,
#else
- debug_nothing_tree, /* begin_function */
+ debug_nothing_tree, /* begin_function */
#endif
- debug_nothing_int, /* end_function */
+ debug_nothing_int, /* end_function */
dbxout_function_decl,
- dbxout_global_decl, /* global_decl */
- debug_nothing_tree, /* deferred_inline_function */
- debug_nothing_tree, /* outlining_inline_function */
- debug_nothing_rtx, /* label */
- dbxout_handle_pch /* handle_pch */
+ dbxout_global_decl, /* global_decl */
+ dbxout_type_decl, /* type_decl */
+ debug_nothing_tree_tree, /* imported_module_or_decl */
+ debug_nothing_tree, /* deferred_inline_function */
+ debug_nothing_tree, /* outlining_inline_function */
+ debug_nothing_rtx, /* label */
+ dbxout_handle_pch, /* handle_pch */
+ debug_nothing_rtx, /* var_location */
+ debug_nothing_void, /* switch_text_section */
+ 0 /* start_end_main_source_file */
};
#endif /* DBX_DEBUGGING_INFO */
@@ -413,61 +390,591 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
dbxout_end_source_file,
xcoffout_begin_block,
xcoffout_end_block,
- debug_true_tree, /* ignore_block */
+ debug_true_tree, /* ignore_block */
xcoffout_source_line,
- xcoffout_begin_prologue, /* begin_prologue */
- debug_nothing_int_charstar, /* end_prologue */
+ xcoffout_begin_prologue, /* begin_prologue */
+ debug_nothing_int_charstar, /* end_prologue */
xcoffout_end_epilogue,
- debug_nothing_tree, /* begin_function */
+ debug_nothing_tree, /* begin_function */
xcoffout_end_function,
- debug_nothing_tree, /* function_decl */
- dbxout_global_decl, /* global_decl */
- debug_nothing_tree, /* deferred_inline_function */
- debug_nothing_tree, /* outlining_inline_function */
- debug_nothing_rtx, /* label */
- dbxout_handle_pch /* handle_pch */
+ debug_nothing_tree, /* function_decl */
+ dbxout_global_decl, /* global_decl */
+ dbxout_type_decl, /* type_decl */
+ debug_nothing_tree_tree, /* imported_module_or_decl */
+ debug_nothing_tree, /* deferred_inline_function */
+ debug_nothing_tree, /* outlining_inline_function */
+ debug_nothing_rtx, /* label */
+ dbxout_handle_pch, /* handle_pch */
+ debug_nothing_rtx, /* var_location */
+ debug_nothing_void, /* switch_text_section */
+ 0 /* start_end_main_source_file */
};
#endif /* XCOFF_DEBUGGING_INFO */
+/* Numeric formatting helper macro. Note that this does not handle
+ hexadecimal. */
+#define NUMBER_FMT_LOOP(P, NUM, BASE) \
+ do \
+ { \
+ int digit = NUM % BASE; \
+ NUM /= BASE; \
+ *--P = digit + '0'; \
+ } \
+ while (NUM > 0)
+
+/* Utility: write a decimal integer NUM to asm_out_file. */
+void
+dbxout_int (int num)
+{
+ char buf[64];
+ char *p = buf + sizeof buf;
+ unsigned int unum;
+
+ if (num == 0)
+ {
+ putc ('0', asm_out_file);
+ return;
+ }
+ if (num < 0)
+ {
+ putc ('-', asm_out_file);
+ unum = -num;
+ }
+ else
+ unum = num;
+
+ NUMBER_FMT_LOOP (p, unum, 10);
+
+ while (p < buf + sizeof buf)
+ {
+ putc (*p, asm_out_file);
+ p++;
+ }
+}
+
+
+/* Primitives for emitting simple stabs directives. All other stabs
+ routines should use these functions instead of directly emitting
+ stabs. They are exported because machine-dependent code may need
+ to invoke them, e.g. in a DBX_OUTPUT_* macro whose definition
+ forwards to code in CPU.c. */
+
+/* The following functions should all be called immediately after one
+ of the dbxout_begin_stab* functions (below). They write out
+ various things as the value of a stab. */
+
+/* Write out a literal zero as the value of a stab. */
+void
+dbxout_stab_value_zero (void)
+{
+ fputs ("0\n", asm_out_file);
+}
+
+/* Write out the label LABEL as the value of a stab. */
+void
+dbxout_stab_value_label (const char *label)
+{
+ assemble_name (asm_out_file, label);
+ putc ('\n', asm_out_file);
+}
+
+/* Write out the difference of two labels, LABEL - BASE, as the value
+ of a stab. */
+void
+dbxout_stab_value_label_diff (const char *label, const char *base)
+{
+ assemble_name (asm_out_file, label);
+ putc ('-', asm_out_file);
+ assemble_name (asm_out_file, base);
+ putc ('\n', asm_out_file);
+}
+
+/* Write out an internal label as the value of a stab, and immediately
+ emit that internal label. This should be used only when
+ dbxout_stabd will not work. STEM is the name stem of the label,
+ COUNTERP is a pointer to a counter variable which will be used to
+ guarantee label uniqueness. */
+void
+dbxout_stab_value_internal_label (const char *stem, int *counterp)
+{
+ char label[100];
+ int counter = counterp ? (*counterp)++ : 0;
+
+ ASM_GENERATE_INTERNAL_LABEL (label, stem, counter);
+ dbxout_stab_value_label (label);
+ targetm.asm_out.internal_label (asm_out_file, stem, counter);
+}
+
+/* Write out the difference between BASE and an internal label as the
+ value of a stab, and immediately emit that internal label. STEM and
+ COUNTERP are as for dbxout_stab_value_internal_label. */
+void
+dbxout_stab_value_internal_label_diff (const char *stem, int *counterp,
+ const char *base)
+{
+ char label[100];
+ int counter = counterp ? (*counterp)++ : 0;
+
+ ASM_GENERATE_INTERNAL_LABEL (label, stem, counter);
+ dbxout_stab_value_label_diff (label, base);
+ targetm.asm_out.internal_label (asm_out_file, stem, counter);
+}
+
+/* The following functions produce specific kinds of stab directives. */
+
+/* Write a .stabd directive with type STYPE and desc SDESC to asm_out_file. */
+void
+dbxout_stabd (int stype, int sdesc)
+{
+ fputs (ASM_STABD_OP, asm_out_file);
+ dbxout_int (stype);
+ fputs (",0,", asm_out_file);
+ dbxout_int (sdesc);
+ putc ('\n', asm_out_file);
+}
+
+/* Write a .stabn directive with type STYPE. This function stops
+ short of emitting the value field, which is the responsibility of
+ the caller (normally it will be either a symbol or the difference
+ of two symbols). */
+
+void
+dbxout_begin_stabn (int stype)
+{
+ fputs (ASM_STABN_OP, asm_out_file);
+ dbxout_int (stype);
+ fputs (",0,0,", asm_out_file);
+}
+
+/* Write a .stabn directive with type N_SLINE and desc LINE. As above,
+ the value field is the responsibility of the caller. */
+void
+dbxout_begin_stabn_sline (int lineno)
+{
+ fputs (ASM_STABN_OP, asm_out_file);
+ dbxout_int (N_SLINE);
+ fputs (",0,", asm_out_file);
+ dbxout_int (lineno);
+ putc (',', asm_out_file);
+}
+
+/* Begin a .stabs directive with string "", type STYPE, and desc and
+ other fields 0. The value field is the responsibility of the
+ caller. This function cannot be used for .stabx directives. */
+void
+dbxout_begin_empty_stabs (int stype)
+{
+ fputs (ASM_STABS_OP, asm_out_file);
+ fputs ("\"\",", asm_out_file);
+ dbxout_int (stype);
+ fputs (",0,0,", asm_out_file);
+}
+
+/* Begin a .stabs directive with string STR, type STYPE, and desc 0.
+ The value field is the responsibility of the caller. */
+void
+dbxout_begin_simple_stabs (const char *str, int stype)
+{
+ fputs (ASM_STABS_OP, asm_out_file);
+ output_quoted_string (asm_out_file, str);
+ putc (',', asm_out_file);
+ dbxout_int (stype);
+ fputs (",0,0,", asm_out_file);
+}
+
+/* As above but use SDESC for the desc field. */
+void
+dbxout_begin_simple_stabs_desc (const char *str, int stype, int sdesc)
+{
+ fputs (ASM_STABS_OP, asm_out_file);
+ output_quoted_string (asm_out_file, str);
+ putc (',', asm_out_file);
+ dbxout_int (stype);
+ fputs (",0,", asm_out_file);
+ dbxout_int (sdesc);
+ putc (',', asm_out_file);
+}
+
+/* The next set of functions are entirely concerned with production of
+ "complex" .stabs directives: that is, .stabs directives whose
+ strings have to be constructed piecemeal. dbxout_type,
+ dbxout_symbol, etc. use these routines heavily. The string is queued
+ up in an obstack, then written out by dbxout_finish_complex_stabs, which
+ is also responsible for splitting it up if it exceeds DBX_CONTIN_LENGTH.
+ (You might think it would be more efficient to go straight to stdio
+ when DBX_CONTIN_LENGTH is 0 (i.e. no length limit) but that turns
+ out not to be the case, and anyway this needs fewer #ifdefs.) */
+
+/* Begin a complex .stabs directive. If we can, write the initial
+ ASM_STABS_OP to the asm_out_file. */
+
+static void
+dbxout_begin_complex_stabs (void)
+{
+ emit_pending_bincls_if_required ();
+ FORCE_TEXT;
+ fputs (ASM_STABS_OP, asm_out_file);
+ putc ('"', asm_out_file);
+ gcc_assert (stabstr_last_contin_point == 0);
+}
+
+/* As above, but do not force text or emit pending bincls. This is
+ used by dbxout_symbol_location, which needs to do something else. */
+static void
+dbxout_begin_complex_stabs_noforcetext (void)
+{
+ fputs (ASM_STABS_OP, asm_out_file);
+ putc ('"', asm_out_file);
+ gcc_assert (stabstr_last_contin_point == 0);
+}
+
+/* Add CHR, a single character, to the string being built. */
+#define stabstr_C(chr) obstack_1grow (&stabstr_ob, chr)
+
+/* Add STR, a normal C string, to the string being built. */
+#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen(str))
+
+/* Add the text of ID, an IDENTIFIER_NODE, to the string being built. */
+#define stabstr_I(id) obstack_grow (&stabstr_ob, \
+ IDENTIFIER_POINTER (id), \
+ IDENTIFIER_LENGTH (id))
+
+/* Add NUM, a signed decimal number, to the string being built. */
+static void
+stabstr_D (HOST_WIDE_INT num)
+{
+ char buf[64];
+ char *p = buf + sizeof buf;
+ unsigned int unum;
+
+ if (num == 0)
+ {
+ stabstr_C ('0');
+ return;
+ }
+ if (num < 0)
+ {
+ stabstr_C ('-');
+ unum = -num;
+ }
+ else
+ unum = num;
+
+ NUMBER_FMT_LOOP (p, unum, 10);
+
+ obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+}
+
+/* Add NUM, an unsigned decimal number, to the string being built. */
+static void
+stabstr_U (unsigned HOST_WIDE_INT num)
+{
+ char buf[64];
+ char *p = buf + sizeof buf;
+ if (num == 0)
+ {
+ stabstr_C ('0');
+ return;
+ }
+ NUMBER_FMT_LOOP (p, num, 10);
+ obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+}
+
+/* Add CST, an INTEGER_CST tree, to the string being built as an
+ unsigned octal number. This routine handles values which are
+ larger than a single HOST_WIDE_INT. */
+static void
+stabstr_O (tree cst)
+{
+ unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (cst);
+ unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
+
+ char buf[128];
+ char *p = buf + sizeof buf;
+
+ /* GDB wants constants with no extra leading "1" bits, so
+ we need to remove any sign-extension that might be
+ present. */
+ {
+ const unsigned int width = TYPE_PRECISION (TREE_TYPE (cst));
+ if (width == HOST_BITS_PER_WIDE_INT * 2)
+ ;
+ else if (width > HOST_BITS_PER_WIDE_INT)
+ high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
+ else if (width == HOST_BITS_PER_WIDE_INT)
+ high = 0;
+ else
+ high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
+ }
+
+ /* Leading zero for base indicator. */
+ stabstr_C ('0');
+
+ /* If the value is zero, the base indicator will serve as the value
+ all by itself. */
+ if (high == 0 && low == 0)
+ return;
+
+ /* If the high half is zero, we need only print the low half normally. */
+ if (high == 0)
+ NUMBER_FMT_LOOP (p, low, 8);
+ else
+ {
+ /* When high != 0, we need to print enough zeroes from low to
+ give the digits from high their proper place-values. Hence
+ NUMBER_FMT_LOOP cannot be used. */
+ const int n_digits = HOST_BITS_PER_WIDE_INT / 3;
+ int i;
+
+ for (i = 1; i <= n_digits; i++)
+ {
+ unsigned int digit = low % 8;
+ low /= 8;
+ *--p = '0' + digit;
+ }
+
+ /* Octal digits carry exactly three bits of information. The
+ width of a HOST_WIDE_INT is not normally a multiple of three.
+ Therefore, the next digit printed probably needs to carry
+ information from both low and high. */
+ if (HOST_BITS_PER_WIDE_INT % 3 != 0)
+ {
+ const int n_leftover_bits = HOST_BITS_PER_WIDE_INT % 3;
+ const int n_bits_from_high = 3 - n_leftover_bits;
+
+ const unsigned HOST_WIDE_INT
+ low_mask = (((unsigned HOST_WIDE_INT)1) << n_leftover_bits) - 1;
+ const unsigned HOST_WIDE_INT
+ high_mask = (((unsigned HOST_WIDE_INT)1) << n_bits_from_high) - 1;
+
+ unsigned int digit;
+
+ /* At this point, only the bottom n_leftover_bits bits of low
+ should be set. */
+ gcc_assert (!(low & ~low_mask));
+
+ digit = (low | ((high & high_mask) << n_leftover_bits));
+ high >>= n_bits_from_high;
+
+ *--p = '0' + digit;
+ }
+
+ /* Now we can format high in the normal manner. However, if
+ the only bits of high that were set were handled by the
+ digit split between low and high, high will now be zero, and
+ we don't want to print extra digits in that case. */
+ if (high)
+ NUMBER_FMT_LOOP (p, high, 8);
+ }
+
+ obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+}
+
+/* Called whenever it is safe to break a stabs string into multiple
+ .stabs directives. If the current string has exceeded the limit
+ set by DBX_CONTIN_LENGTH, mark the current position in the buffer
+ as a continuation point by inserting DBX_CONTIN_CHAR (doubled if
+ it is a backslash) and a null character. */
+static inline void
+stabstr_continue (void)
+{
+ if (DBX_CONTIN_LENGTH > 0
+ && obstack_object_size (&stabstr_ob) - stabstr_last_contin_point
+ > DBX_CONTIN_LENGTH)
+ {
+ if (DBX_CONTIN_CHAR == '\\')
+ obstack_1grow (&stabstr_ob, '\\');
+ obstack_1grow (&stabstr_ob, DBX_CONTIN_CHAR);
+ obstack_1grow (&stabstr_ob, '\0');
+ stabstr_last_contin_point = obstack_object_size (&stabstr_ob);
+ }
+}
+#define CONTIN stabstr_continue ()
+
+/* Macro subroutine of dbxout_finish_complex_stabs, which emits
+ all of the arguments to the .stabs directive after the string.
+ Overridden by xcoffout.h. CODE is the stabs code for this symbol;
+ LINE is the source line to write into the desc field (in extended
+ mode); SYM is the symbol itself.
+
+ ADDR, LABEL, and NUMBER are three different ways to represent the
+ stabs value field. At most one of these should be nonzero.
+
+ ADDR is used most of the time; it represents the value as an
+ RTL address constant.
+
+ LABEL is used (currently) only for N_CATCH stabs; it represents
+ the value as a string suitable for assemble_name.
+
+ NUMBER is used when the value is an offset from an implicit base
+ pointer (e.g. for a stack variable), or an index (e.g. for a
+ register variable). It represents the value as a decimal integer. */
+
+#ifndef DBX_FINISH_STABS
+#define DBX_FINISH_STABS(SYM, CODE, LINE, ADDR, LABEL, NUMBER) \
+do { \
+ int line_ = use_gnu_debug_info_extensions ? LINE : 0; \
+ \
+ dbxout_int (CODE); \
+ fputs (",0,", asm_out_file); \
+ dbxout_int (line_); \
+ putc (',', asm_out_file); \
+ if (ADDR) \
+ output_addr_const (asm_out_file, ADDR); \
+ else if (LABEL) \
+ assemble_name (asm_out_file, LABEL); \
+ else \
+ dbxout_int (NUMBER); \
+ putc ('\n', asm_out_file); \
+} while (0)
+#endif
+
+/* Finish the emission of a complex .stabs directive. When DBX_CONTIN_LENGTH
+ is zero, this has only to emit the close quote and the remainder of
+ the arguments. When it is nonzero, the string has been marshalled in
+ stabstr_ob, and this routine is responsible for breaking it up into
+ DBX_CONTIN_LENGTH-sized chunks.
+
+ SYM is the DECL of the symbol under consideration; it is used only
+ for its DECL_SOURCE_LINE. The other arguments are all passed directly
+ to DBX_FINISH_STABS; see above for details. */
+
+static void
+dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code,
+ rtx addr, const char *label, int number)
+{
+ int line ATTRIBUTE_UNUSED;
+ char *str;
+ size_t len;
+
+ line = sym ? DECL_SOURCE_LINE (sym) : 0;
+ if (DBX_CONTIN_LENGTH > 0)
+ {
+ char *chunk;
+ size_t chunklen;
+
+ /* Nul-terminate the growing string, then get its size and
+ address. */
+ obstack_1grow (&stabstr_ob, '\0');
+
+ len = obstack_object_size (&stabstr_ob);
+ chunk = str = XOBFINISH (&stabstr_ob, char *);
+
+ /* Within the buffer are a sequence of NUL-separated strings,
+ each of which is to be written out as a separate stab
+ directive. */
+ for (;;)
+ {
+ chunklen = strlen (chunk);
+ fwrite (chunk, 1, chunklen, asm_out_file);
+ fputs ("\",", asm_out_file);
+
+ /* Must add an extra byte to account for the NUL separator. */
+ chunk += chunklen + 1;
+ len -= chunklen + 1;
+
+ /* Only put a line number on the last stab in the sequence. */
+ DBX_FINISH_STABS (sym, code, len == 0 ? line : 0,
+ addr, label, number);
+ if (len == 0)
+ break;
+
+ fputs (ASM_STABS_OP, asm_out_file);
+ putc ('"', asm_out_file);
+ }
+ stabstr_last_contin_point = 0;
+ }
+ else
+ {
+ /* No continuations - we can put the whole string out at once.
+ It is faster to augment the string with the close quote and
+ comma than to do a two-character fputs. */
+ obstack_grow (&stabstr_ob, "\",", 2);
+ len = obstack_object_size (&stabstr_ob);
+ str = XOBFINISH (&stabstr_ob, char *);
+
+ fwrite (str, 1, len, asm_out_file);
+ DBX_FINISH_STABS (sym, code, line, addr, label, number);
+ }
+ obstack_free (&stabstr_ob, str);
+}
+
#if defined (DBX_DEBUGGING_INFO)
+
static void
-dbxout_function_end (void)
+dbxout_function_end (tree decl)
{
char lscope_label_name[100];
/* The Lscope label must be emitted even if we aren't doing anything
else; dbxout_block needs it. */
- /* Convert Ltext into the appropriate format for local labels in case
+ switch_to_section (function_section (current_function_decl));
+
+ /* Convert Lscope into the appropriate format for local labels in case
the system doesn't insert underscores in front of user generated
labels. */
ASM_GENERATE_INTERNAL_LABEL (lscope_label_name, "Lscope", scope_labelno);
- (*targetm.asm_out.internal_label) (asmfile, "Lscope", scope_labelno);
- scope_labelno++;
+ targetm.asm_out.internal_label (asm_out_file, "Lscope", scope_labelno);
/* The N_FUN tag at the end of the function is a GNU extension,
which may be undesirable, and is unnecessary if we do not have
named sections. */
if (!use_gnu_debug_info_extensions
-#if defined(NO_DBX_FUNCTION_END)
|| NO_DBX_FUNCTION_END
-#endif
- || !targetm.have_named_sections)
+ || !targetm.have_named_sections
+ || DECL_IGNORED_P (decl))
return;
/* By convention, GCC will mark the end of a function with an N_FUN
symbol and an empty string. */
-#ifdef DBX_OUTPUT_NFUN
- DBX_OUTPUT_NFUN (asmfile, lscope_label_name, current_function_decl);
-#else
- fprintf (asmfile, "%s\"\",%d,0,0,", ASM_STABS_OP, N_FUN);
- assemble_name (asmfile, lscope_label_name);
- putc ('-', asmfile);
- assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
- fprintf (asmfile, "\n");
-#endif
+ if (flag_reorder_blocks_and_partition)
+ {
+ dbxout_begin_empty_stabs (N_FUN);
+ dbxout_stab_value_label_diff (cfun->hot_section_end_label,
+ cfun->hot_section_label);
+ dbxout_begin_empty_stabs (N_FUN);
+ dbxout_stab_value_label_diff (cfun->cold_section_end_label,
+ cfun->cold_section_label);
+ }
+ else
+ {
+ char begin_label[20];
+ /* Reference current function start using LFBB. */
+ ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
+ dbxout_begin_empty_stabs (N_FUN);
+ dbxout_stab_value_label_diff (lscope_label_name, begin_label);
+ }
+
+ if (!NO_DBX_BNSYM_ENSYM && !flag_debug_only_used_symbols)
+ dbxout_stabd (N_ENSYM, 0);
}
#endif /* DBX_DEBUGGING_INFO */
+/* Get lang description for N_SO stab. */
+static unsigned int ATTRIBUTE_UNUSED
+get_lang_number (void)
+{
+ const char *language_string = lang_hooks.name;
+
+ if (strcmp (language_string, "GNU C") == 0)
+ return N_SO_C;
+ else if (strcmp (language_string, "GNU C++") == 0)
+ return N_SO_CC;
+ else if (strcmp (language_string, "GNU F77") == 0)
+ return N_SO_FORTRAN;
+ else if (strcmp (language_string, "GNU F95") == 0)
+ return N_SO_FORTRAN90; /* CHECKME */
+ else if (strcmp (language_string, "GNU Pascal") == 0)
+ return N_SO_PASCAL;
+ else if (strcmp (language_string, "GNU Objective-C") == 0)
+ return N_SO_OBJC;
+ else if (strcmp (language_string, "GNU Objective-C++") == 0)
+ return N_SO_OBJCPLUS;
+ else
+ return 0;
+
+}
+
/* At the beginning of compilation, start writing the symbol table.
Initialize `typevec' and output the standard data types of C. */
@@ -475,59 +982,62 @@ static void
dbxout_init (const char *input_file_name)
{
char ltext_label_name[100];
- tree syms = (*lang_hooks.decls.getdecls) ();
-
- asmfile = asm_out_file;
+ bool used_ltext_label_name = false;
+ tree syms = lang_hooks.decls.getdecls ();
typevec_len = 100;
typevec = ggc_calloc (typevec_len, sizeof typevec[0]);
+ /* stabstr_ob contains one string, which will be just fine with
+ 1-byte alignment. */
+ obstack_specify_allocation (&stabstr_ob, 0, 1, xmalloc, free);
+
/* Convert Ltext into the appropriate format for local labels in case
the system doesn't insert underscores in front of user generated
labels. */
ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
/* Put the current working directory in an N_SO symbol. */
- if (use_gnu_debug_info_extensions)
+ if (use_gnu_debug_info_extensions && !NO_DBX_MAIN_SOURCE_DIRECTORY)
{
- if (!cwd && (cwd = get_src_pwd ())
- && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
- cwd = concat (cwd, FILE_NAME_JOINER, NULL);
- if (cwd)
+ static const char *cwd;
+
+ if (!cwd)
{
+ cwd = get_src_pwd ();
+ if (cwd[0] == '\0')
+ cwd = "/";
+ else if (!IS_DIR_SEPARATOR (cwd[strlen (cwd) - 1]))
+ cwd = concat (cwd, "/", NULL);
+ }
#ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
- DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asmfile, cwd);
+ DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asm_out_file, cwd);
#else /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
- fprintf (asmfile, "%s", ASM_STABS_OP);
- output_quoted_string (asmfile, cwd);
- fprintf (asmfile, ",%d,0,0,", N_SO);
- assemble_name (asmfile, ltext_label_name);
- fputc ('\n', asmfile);
+ dbxout_begin_simple_stabs_desc (cwd, N_SO, get_lang_number ());
+ dbxout_stab_value_label (ltext_label_name);
+ used_ltext_label_name = true;
#endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
- }
}
#ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME
- DBX_OUTPUT_MAIN_SOURCE_FILENAME (asmfile, input_file_name);
-#else /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */
- /* We include outputting `Ltext:' here,
- because that gives you a way to override it. */
- /* Used to put `Ltext:' before the reference, but that loses on sun 4. */
- fprintf (asmfile, "%s", ASM_STABS_OP);
- output_quoted_string (asmfile, input_file_name);
- fprintf (asmfile, ",%d,0,0,", N_SO);
- assemble_name (asmfile, ltext_label_name);
- fputc ('\n', asmfile);
- text_section ();
- (*targetm.asm_out.internal_label) (asmfile, "Ltext", 0);
-#endif /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */
-
-#ifdef DBX_OUTPUT_GCC_MARKER
- DBX_OUTPUT_GCC_MARKER (asmfile);
+ DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, input_file_name);
#else
- /* Emit an N_OPT stab to indicate that this file was compiled by GCC. */
- fprintf (asmfile, "%s\"%s\",%d,0,0,0\n",
- ASM_STABS_OP, STABS_GCC_MARKER, N_OPT);
+ dbxout_begin_simple_stabs_desc (input_file_name, N_SO, get_lang_number ());
+ dbxout_stab_value_label (ltext_label_name);
+ used_ltext_label_name = true;
+#endif
+
+ if (used_ltext_label_name)
+ {
+ switch_to_section (text_section);
+ targetm.asm_out.internal_label (asm_out_file, "Ltext", 0);
+ }
+
+ /* Emit an N_OPT stab to indicate that this file was compiled by GCC.
+ The string used is historical. */
+#ifndef NO_DBX_GCC_MARKER
+ dbxout_begin_simple_stabs ("gcc2_compiled.", N_OPT);
+ dbxout_stab_value_zero ();
#endif
base_input_file = lastfile = input_file_name;
@@ -535,7 +1045,7 @@ dbxout_init (const char *input_file_name)
next_type_number = 1;
#ifdef DBX_USE_BINCL
- current_file = xmalloc (sizeof *current_file);
+ current_file = XNEW (struct dbx_file);
current_file->next = NULL;
current_file->file_number = 0;
current_file->next_type_number = 1;
@@ -545,22 +1055,20 @@ dbxout_init (const char *input_file_name)
current_file->pending_bincl_name = NULL;
#endif
- /* Make sure that types `int' and `char' have numbers 1 and 2.
- Definitions of other integer types will refer to those numbers.
- (Actually it should no longer matter what their numbers are.
- Also, if any types with tags have been defined, dbxout_symbol
- will output them first, so the numbers won't be 1 and 2. That
- happens in C++. So it's a good thing it should no longer matter). */
-
-#ifdef DBX_OUTPUT_STANDARD_TYPES
- DBX_OUTPUT_STANDARD_TYPES (syms);
-#endif
-
/* Get all permanent types that have typedef names, and output them
all, except for those already output. Some language front ends
- put these declarations in the top-level scope; some do not. */
- dbxout_typedefs ((*lang_hooks.decls.builtin_type_decls) ());
+ put these declarations in the top-level scope; some do not;
+ the latter are responsible for calling debug_hooks->type_decl from
+ their record_builtin_type function. */
dbxout_typedefs (syms);
+
+ if (preinit_symbols)
+ {
+ tree t;
+ for (t = nreverse (preinit_symbols); t; t = TREE_CHAIN (t))
+ dbxout_symbol (TREE_VALUE (t), 0);
+ preinit_symbols = 0;
+ }
}
/* Output any typedef names for types described by TYPE_DECLs in SYMS. */
@@ -587,9 +1095,8 @@ dbxout_typedefs (tree syms)
static void
emit_bincl_stab (const char *name)
{
- fprintf (asmfile, "%s", ASM_STABS_OP);
- output_quoted_string (asmfile, name);
- fprintf (asmfile, ",%d,0,0,0\n", N_BINCL);
+ dbxout_begin_simple_stabs (name, N_BINCL);
+ dbxout_stab_value_zero ();
}
/* If there are pending bincls then it is time to emit all of them. */
@@ -647,7 +1154,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
const char *filename ATTRIBUTE_UNUSED)
{
#ifdef DBX_USE_BINCL
- struct dbx_file *n = xmalloc (sizeof *n);
+ struct dbx_file *n = XNEW (struct dbx_file);
n->next = current_file;
n->next_type_number = 1;
@@ -671,7 +1178,10 @@ dbxout_end_source_file (unsigned int line ATTRIBUTE_UNUSED)
#ifdef DBX_USE_BINCL
/* Emit EINCL stab only if BINCL is not pending. */
if (current_file->bincl_status == BINCL_PROCESSED)
- fprintf (asmfile, "%s%d,0,0,0\n", ASM_STABN_OP, N_EINCL);
+ {
+ dbxout_begin_stabn (N_EINCL);
+ dbxout_stab_value_zero ();
+ }
current_file->bincl_status = BINCL_NOT_REQUIRED;
current_file = current_file->next;
#endif
@@ -706,7 +1216,7 @@ dbxout_handle_pch (unsigned at_end)
/* Output debugging info to FILE to switch to sourcefile FILENAME. */
static void
-dbxout_source_file (FILE *file, const char *filename)
+dbxout_source_file (const char *filename)
{
if (lastfile == 0 && lastfile_is_base)
{
@@ -716,39 +1226,60 @@ dbxout_source_file (FILE *file, const char *filename)
if (filename && (lastfile == 0 || strcmp (filename, lastfile)))
{
- char ltext_label_name[100];
-
- ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext",
- source_label_number);
- fprintf (file, "%s", ASM_STABS_OP);
- output_quoted_string (file, filename);
- fprintf (asmfile, ",%d,0,0,", N_SOL);
- assemble_name (asmfile, ltext_label_name);
- fputc ('\n', asmfile);
- if (current_function_decl != NULL_TREE
- && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
- ; /* Don't change section amid function. */
- else
- text_section ();
- (*targetm.asm_out.internal_label) (file, "Ltext", source_label_number);
- source_label_number++;
+ /* Don't change section amid function. */
+ if (current_function_decl == NULL_TREE)
+ switch_to_section (text_section);
+
+ dbxout_begin_simple_stabs (filename, N_SOL);
+ dbxout_stab_value_internal_label ("Ltext", &source_label_number);
lastfile = filename;
}
}
+/* Output N_BNSYM, line number symbol entry, and local symbol at
+ function scope */
+
+static void
+dbxout_begin_prologue (unsigned int lineno, const char *filename)
+{
+ if (use_gnu_debug_info_extensions
+ && !NO_DBX_FUNCTION_END
+ && !NO_DBX_BNSYM_ENSYM
+ && !flag_debug_only_used_symbols)
+ dbxout_stabd (N_BNSYM, 0);
+
+ /* pre-increment the scope counter */
+ scope_labelno++;
+
+ dbxout_source_line (lineno, filename);
+ /* Output function begin block at function scope, referenced
+ by dbxout_block, dbxout_source_line and dbxout_function_end. */
+ emit_pending_bincls_if_required ();
+ targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno);
+}
+
/* Output a line number symbol entry for source file FILENAME and line
number LINENO. */
static void
dbxout_source_line (unsigned int lineno, const char *filename)
{
- dbxout_source_file (asmfile, filename);
+ dbxout_source_file (filename);
-#ifdef ASM_OUTPUT_SOURCE_LINE
- dbxout_source_line_counter += 1;
- ASM_OUTPUT_SOURCE_LINE (asmfile, lineno, dbxout_source_line_counter);
+#ifdef DBX_OUTPUT_SOURCE_LINE
+ DBX_OUTPUT_SOURCE_LINE (asm_out_file, lineno, dbxout_source_line_counter);
#else
- fprintf (asmfile, "%s%d,0,%d\n", ASM_STABD_OP, N_SLINE, lineno);
+ if (DBX_LINES_FUNCTION_RELATIVE)
+ {
+ char begin_label[20];
+ dbxout_begin_stabn_sline (lineno);
+ /* Reference current function start using LFBB. */
+ ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
+ dbxout_stab_value_internal_label_diff ("LM", &dbxout_source_line_counter,
+ begin_label);
+ }
+ else
+ dbxout_stabd (N_SLINE, lineno);
#endif
}
@@ -758,7 +1289,7 @@ static void
dbxout_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
{
emit_pending_bincls_if_required ();
- (*targetm.asm_out.internal_label) (asmfile, "LBB", n);
+ targetm.asm_out.internal_label (asm_out_file, "LBB", n);
}
/* Describe the end line-number of an internal block within a function. */
@@ -767,7 +1298,7 @@ static void
dbxout_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
{
emit_pending_bincls_if_required ();
- (*targetm.asm_out.internal_label) (asmfile, "LBE", n);
+ targetm.asm_out.internal_label (asm_out_file, "LBE", n);
}
/* Output dbx data for a function definition.
@@ -784,10 +1315,7 @@ dbxout_function_decl (tree decl)
dbxout_begin_function (decl);
#endif
dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
-#ifdef DBX_OUTPUT_FUNCTION_END
- DBX_OUTPUT_FUNCTION_END (asmfile, decl);
-#endif
- dbxout_function_end ();
+ dbxout_function_end (decl);
}
#endif /* DBX_DEBUGGING_INFO */
@@ -797,9 +1325,7 @@ dbxout_function_decl (tree decl)
static void
dbxout_global_decl (tree decl)
{
- if (TREE_CODE (decl) == VAR_DECL
- && ! DECL_EXTERNAL (decl)
- && DECL_RTL_SET_P (decl)) /* Not necessary? */
+ if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
{
int saved_tree_used = TREE_USED (decl);
TREE_USED (decl) = 1;
@@ -808,17 +1334,29 @@ dbxout_global_decl (tree decl)
}
}
+/* This is just a function-type adapter; dbxout_symbol does exactly
+ what we want but returns an int. */
+static void
+dbxout_type_decl (tree decl, int local)
+{
+ dbxout_symbol (decl, local);
+}
+
/* At the end of compilation, finish writing the symbol table.
- Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is
- to do nothing. */
+ The default is to call debug_free_queue but do nothing else. */
static void
dbxout_finish (const char *filename ATTRIBUTE_UNUSED)
{
#ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END
- DBX_OUTPUT_MAIN_SOURCE_FILE_END (asmfile, filename);
-#endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */
-
+ DBX_OUTPUT_MAIN_SOURCE_FILE_END (asm_out_file, filename);
+#elif defined DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+ {
+ switch_to_section (text_section);
+ dbxout_begin_empty_stabs (N_SO);
+ dbxout_stab_value_internal_label ("Letext", 0);
+ }
+#endif
debug_free_queue ();
}
@@ -828,37 +1366,24 @@ static void
dbxout_type_index (tree type)
{
#ifndef DBX_USE_BINCL
- fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
- CHARS (3);
+ stabstr_D (TYPE_SYMTAB_ADDRESS (type));
#else
struct typeinfo *t = &typevec[TYPE_SYMTAB_ADDRESS (type)];
- fprintf (asmfile, "(%d,%d)", t->file_number, t->type_number);
- CHARS (9);
+ stabstr_C ('(');
+ stabstr_D (t->file_number);
+ stabstr_C (',');
+ stabstr_D (t->type_number);
+ stabstr_C (')');
#endif
}
-#if DBX_CONTIN_LENGTH > 0
-/* Continue a symbol-description that gets too big.
- End one symbol table entry with a double-backslash
- and start a new one, eventually producing something like
- .stabs "start......\\",code,0,value
- .stabs "...rest",code,0,value */
-
-static void
-dbxout_continue (void)
-{
- emit_pending_bincls_if_required ();
-#ifdef DBX_CONTIN_CHAR
- fprintf (asmfile, "%c", DBX_CONTIN_CHAR);
-#else
- fprintf (asmfile, "\\\\");
-#endif
- dbxout_finish_symbol (NULL_TREE);
- fprintf (asmfile, "%s\"", ASM_STABS_OP);
- current_sym_nchars = 0;
-}
-#endif /* DBX_CONTIN_LENGTH > 0 */
+
+/* Used in several places: evaluates to '0' for a private decl,
+ '1' for a protected decl, '2' for a public decl. */
+#define DECL_ACCESSIBILITY_CHAR(DECL) \
+(TREE_PRIVATE (DECL) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2')
+
/* Subroutine of `dbxout_type'. Output the type fields of TYPE.
This must be a separate function because anonymous unions require
recursive calls. */
@@ -872,21 +1397,21 @@ dbxout_type_fields (tree type)
field that we can support. */
for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
{
-
- /* If on of the nodes is an error_mark or its type is then return early. */
+ /* If one of the nodes is an error_mark or its type is then
+ return early. */
if (tem == error_mark_node || TREE_TYPE (tem) == error_mark_node)
return;
/* Omit here local type decls until we know how to support them. */
if (TREE_CODE (tem) == TYPE_DECL
+ /* Omit here the nameless fields that are used to skip bits. */
+ || DECL_IGNORED_P (tem)
/* Omit fields whose position or size are variable or too large to
represent. */
|| (TREE_CODE (tem) == FIELD_DECL
&& (! host_integerp (bit_position (tem), 0)
|| ! DECL_SIZE (tem)
- || ! host_integerp (DECL_SIZE (tem), 1)))
- /* Omit here the nameless fields that are used to skip bits. */
- || DECL_IGNORED_P (tem))
+ || ! host_integerp (DECL_SIZE (tem), 1))))
continue;
else if (TREE_CODE (tem) != CONST_DECL)
@@ -897,26 +1422,15 @@ dbxout_type_fields (tree type)
CONTIN;
if (DECL_NAME (tem))
- {
- fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem)));
- CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem)));
- }
- else
- {
- fprintf (asmfile, ":");
- CHARS (1);
- }
+ stabstr_I (DECL_NAME (tem));
+ stabstr_C (':');
if (use_gnu_debug_info_extensions
&& (TREE_PRIVATE (tem) || TREE_PROTECTED (tem)
|| TREE_CODE (tem) != FIELD_DECL))
{
- have_used_extensions = 1;
- putc ('/', asmfile);
- putc ((TREE_PRIVATE (tem) ? '0'
- : TREE_PROTECTED (tem) ? '1' : '2'),
- asmfile);
- CHARS (2);
+ stabstr_C ('/');
+ stabstr_C (DECL_ACCESSIBILITY_CHAR (tem));
}
dbxout_type ((TREE_CODE (tem) == FIELD_DECL
@@ -929,37 +1443,31 @@ dbxout_type_fields (tree type)
{
tree name = DECL_ASSEMBLER_NAME (tem);
- have_used_extensions = 1;
- fprintf (asmfile, ":%s;", IDENTIFIER_POINTER (name));
- CHARS (IDENTIFIER_LENGTH (name) + 2);
+ stabstr_C (':');
+ stabstr_I (name);
+ stabstr_C (';');
}
else
- {
- /* If TEM is non-static, GDB won't understand it. */
- fprintf (asmfile, ",0,0;");
- CHARS (5);
- }
+ /* If TEM is non-static, GDB won't understand it. */
+ stabstr_S (",0,0;");
}
else
{
- putc (',', asmfile);
- print_wide_int (int_bit_position (tem));
- putc (',', asmfile);
- print_wide_int (tree_low_cst (DECL_SIZE (tem), 1));
- putc (';', asmfile);
- CHARS (3);
+ stabstr_C (',');
+ stabstr_D (int_bit_position (tem));
+ stabstr_C (',');
+ stabstr_D (tree_low_cst (DECL_SIZE (tem), 1));
+ stabstr_C (';');
}
}
}
}
/* Subroutine of `dbxout_type_methods'. Output debug info about the
- method described DECL. DEBUG_NAME is an encoding of the method's
- type signature. ??? We may be able to do without DEBUG_NAME altogether
- now. */
+ method described DECL. */
static void
-dbxout_type_method_1 (tree decl, const char *debug_name)
+dbxout_type_method_1 (tree decl)
{
char c1 = 'A', c2;
@@ -983,20 +1491,21 @@ dbxout_type_method_1 (tree decl, const char *debug_name)
c2 = '.';
}
- fprintf (asmfile, ":%s;%c%c%c", debug_name,
- TREE_PRIVATE (decl) ? '0'
- : TREE_PROTECTED (decl) ? '1' : '2', c1, c2);
- CHARS (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl)) + 6
- - (debug_name - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
+ /* ??? Output the mangled name, which contains an encoding of the
+ method's type signature. May not be necessary anymore. */
+ stabstr_C (':');
+ stabstr_I (DECL_ASSEMBLER_NAME (decl));
+ stabstr_C (';');
+ stabstr_C (DECL_ACCESSIBILITY_CHAR (decl));
+ stabstr_C (c1);
+ stabstr_C (c2);
if (DECL_VINDEX (decl) && host_integerp (DECL_VINDEX (decl), 0))
{
- print_wide_int (tree_low_cst (DECL_VINDEX (decl), 0));
- putc (';', asmfile);
- CHARS (1);
+ stabstr_D (tree_low_cst (DECL_VINDEX (decl), 0));
+ stabstr_C (';');
dbxout_type (DECL_CONTEXT (decl), 0);
- fprintf (asmfile, ";");
- CHARS (1);
+ stabstr_C (';');
}
}
@@ -1008,39 +1517,12 @@ dbxout_type_methods (tree type)
{
/* C++: put out the method names and their parameter lists */
tree methods = TYPE_METHODS (type);
- tree type_encoding;
tree fndecl;
tree last;
- char formatted_type_identifier_length[16];
- int type_identifier_length;
if (methods == NULL_TREE)
return;
- type_encoding = DECL_NAME (TYPE_NAME (type));
-
-#if 0
- /* C++: Template classes break some assumptions made by this code about
- the class names, constructor names, and encodings for assembler
- label names. For now, disable output of dbx info for them. */
- {
- const char *ptr = IDENTIFIER_POINTER (type_encoding);
- /* This should use index. (mrs) */
- while (*ptr && *ptr != '<') ptr++;
- if (*ptr != 0)
- {
- static int warned;
- if (!warned)
- warned = 1;
- return;
- }
- }
-#endif
-
- type_identifier_length = IDENTIFIER_LENGTH (type_encoding);
-
- sprintf (formatted_type_identifier_length, "%d", type_identifier_length);
-
if (TREE_CODE (methods) != TREE_VEC)
fndecl = methods;
else if (TREE_VEC_ELT (methods, 0) != NULL_TREE)
@@ -1061,18 +1543,12 @@ dbxout_type_methods (tree type)
well as the name of the field before overloading, along
with its parameter list */
{
- /* This is the "mangled" name of the method.
- It encodes the argument types. */
- const char *debug_name;
-
/* Skip methods that aren't FUNCTION_DECLs. (In C++, these
include TEMPLATE_DECLs.) The debugger doesn't know what
to do with such entities anyhow. */
if (TREE_CODE (fndecl) != FUNCTION_DECL)
continue;
- debug_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
-
CONTIN;
last = fndecl;
@@ -1086,21 +1562,16 @@ dbxout_type_methods (tree type)
expects. */
if (need_prefix)
{
- tree name = DECL_NAME (fndecl);
- fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
- CHARS (IDENTIFIER_LENGTH (name) + 2);
+ stabstr_I (DECL_NAME (fndecl));
+ stabstr_S ("::");
need_prefix = 0;
}
dbxout_type (TREE_TYPE (fndecl), 0);
-
- dbxout_type_method_1 (fndecl, debug_name);
+ dbxout_type_method_1 (fndecl);
}
if (!need_prefix)
- {
- putc (';', asmfile);
- CHARS (1);
- }
+ stabstr_C (';');
}
}
@@ -1111,7 +1582,7 @@ dbxout_type_methods (tree type)
static void
dbxout_range_type (tree type)
{
- fprintf (asmfile, "r");
+ stabstr_C ('r');
if (TREE_TYPE (type))
dbxout_type (TREE_TYPE (type), 0);
else if (TREE_CODE (type) != INTEGER_TYPE)
@@ -1136,39 +1607,30 @@ dbxout_range_type (tree type)
dbxout_type_index (integer_type_node);
}
+ stabstr_C (';');
if (TYPE_MIN_VALUE (type) != 0
&& host_integerp (TYPE_MIN_VALUE (type), 0))
{
- putc (';', asmfile);
- CHARS (1);
if (print_int_cst_bounds_in_octal_p (type))
- print_int_cst_octal (TYPE_MIN_VALUE (type));
+ stabstr_O (TYPE_MIN_VALUE (type));
else
- print_wide_int (tree_low_cst (TYPE_MIN_VALUE (type), 0));
+ stabstr_D (tree_low_cst (TYPE_MIN_VALUE (type), 0));
}
else
- {
- fprintf (asmfile, ";0");
- CHARS (2);
- }
+ stabstr_C ('0');
+ stabstr_C (';');
if (TYPE_MAX_VALUE (type) != 0
&& host_integerp (TYPE_MAX_VALUE (type), 0))
{
- putc (';', asmfile);
- CHARS (1);
if (print_int_cst_bounds_in_octal_p (type))
- print_int_cst_octal (TYPE_MAX_VALUE (type));
+ stabstr_O (TYPE_MAX_VALUE (type));
else
- print_wide_int (tree_low_cst (TYPE_MAX_VALUE (type), 0));
- putc (';', asmfile);
- CHARS (1);
+ stabstr_D (tree_low_cst (TYPE_MAX_VALUE (type), 0));
+ stabstr_C (';');
}
else
- {
- fprintf (asmfile, ";-1;");
- CHARS (4);
- }
+ stabstr_S ("-1;");
}
@@ -1188,11 +1650,15 @@ dbxout_type (tree type, int full)
tree tem;
tree main_variant;
static int anonymous_type_number = 0;
+ bool vector_type = false;
if (TREE_CODE (type) == VECTOR_TYPE)
- /* The frontend feeds us a representation for the vector as a struct
- containing an array. Pull out the array type. */
- type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
+ {
+ /* The frontend feeds us a representation for the vector as a struct
+ containing an array. Pull out the array type. */
+ type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
+ vector_type = true;
+ }
/* If there was an input error and we don't really have a type,
avoid crashing and write something that is at least valid
@@ -1250,7 +1716,7 @@ dbxout_type (tree type, int full)
|| TREE_CODE (type) == QUAL_UNION_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
&& TYPE_STUB_DECL (type)
- && TREE_CODE_CLASS (TREE_CODE (TYPE_STUB_DECL (type))) == 'd'
+ && DECL_P (TYPE_STUB_DECL (type))
&& ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
debug_queue_symbol (TYPE_STUB_DECL (type));
else if (TYPE_NAME (type)
@@ -1313,9 +1779,7 @@ dbxout_type (tree type, int full)
#endif
/* Output a definition now. */
-
- fprintf (asmfile, "=");
- CHARS (1);
+ stabstr_C ('=');
/* Mark it as defined, so that if it is self-referent
we will not get into an infinite recursion of definitions. */
@@ -1327,15 +1791,13 @@ dbxout_type (tree type, int full)
cv-qualified types if we're using extensions. */
if (TYPE_READONLY (type) > TYPE_READONLY (main_variant))
{
- putc ('k', asmfile);
- CHARS (1);
+ stabstr_C ('k');
dbxout_type (build_type_variant (type, 0, TYPE_VOLATILE (type)), 0);
return;
}
else if (TYPE_VOLATILE (type) > TYPE_VOLATILE (main_variant))
{
- putc ('B', asmfile);
- CHARS (1);
+ stabstr_C ('B');
dbxout_type (build_type_variant (type, TYPE_READONLY (type), 0), 0);
return;
}
@@ -1363,7 +1825,7 @@ dbxout_type (tree type, int full)
{
case VOID_TYPE:
case LANG_TYPE:
- /* For a void type, just define it as itself; ie, "5=5".
+ /* For a void type, just define it as itself; i.e., "5=5".
This makes us consider it defined
without saying what it is. The debugger will make it
a void type when the reference is seen, and nothing will
@@ -1372,18 +1834,16 @@ dbxout_type (tree type, int full)
break;
case INTEGER_TYPE:
- if (type == char_type_node && ! TREE_UNSIGNED (type))
+ if (type == char_type_node && ! TYPE_UNSIGNED (type))
{
/* Output the type `char' as a subrange of itself!
I don't understand this definition, just copied it
from the output of pcc.
This used to use `r2' explicitly and we used to
take care to make sure that `char' was type number 2. */
- fprintf (asmfile, "r");
- CHARS (1);
+ stabstr_C ('r');
dbxout_type_index (type);
- fprintf (asmfile, ";0;127;");
- CHARS (7);
+ stabstr_S (";0;127;");
}
/* If this is a subtype of another integer type, always prefer to
@@ -1397,9 +1857,9 @@ dbxout_type (tree type, int full)
if (use_gnu_debug_info_extensions
&& TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
{
- have_used_extensions = 1;
- fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
- CHARS (5);
+ stabstr_S ("@s");
+ stabstr_D (TYPE_PRECISION (type));
+ stabstr_C (';');
}
dbxout_range_type (type);
@@ -1413,15 +1873,14 @@ dbxout_type (tree type, int full)
if (use_gnu_debug_info_extensions
&& TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
{
- have_used_extensions = 1;
- fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
- CHARS (5);
+ stabstr_S ("@s");
+ stabstr_D (TYPE_PRECISION (type));
+ stabstr_C (';');
}
if (print_int_cst_bounds_in_octal_p (type))
{
- fprintf (asmfile, "r");
- CHARS (1);
+ stabstr_C ('r');
/* If this type derives from another type, output type index of
parent type. This is particularly important when parent type
@@ -1433,14 +1892,11 @@ dbxout_type (tree type, int full)
else
dbxout_type_index (type);
- fprintf (asmfile, ";");
- CHARS (1);
- print_int_cst_octal (TYPE_MIN_VALUE (type));
- fprintf (asmfile, ";");
- CHARS (1);
- print_int_cst_octal (TYPE_MAX_VALUE (type));
- fprintf (asmfile, ";");
- CHARS (1);
+ stabstr_C (';');
+ stabstr_O (TYPE_MIN_VALUE (type));
+ stabstr_C (';');
+ stabstr_O (TYPE_MAX_VALUE (type));
+ stabstr_C (';');
}
else
@@ -1453,59 +1909,22 @@ dbxout_type (tree type, int full)
case REAL_TYPE:
/* This used to say `r1' and we used to take care
to make sure that `int' was type number 1. */
- fprintf (asmfile, "r");
- CHARS (1);
+ stabstr_C ('r');
dbxout_type_index (integer_type_node);
- putc (';', asmfile);
- CHARS (1);
- print_wide_int (int_size_in_bytes (type));
- fputs (";0;", asmfile);
- CHARS (3);
- break;
-
- case CHAR_TYPE:
- if (use_gnu_debug_info_extensions)
- {
- have_used_extensions = 1;
- fputs ("@s", asmfile);
- CHARS (2);
- print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type));
- fputs (";-20;", asmfile);
- CHARS (4);
- }
- else
- {
- /* Output the type `char' as a subrange of itself.
- That is what pcc seems to do. */
- fprintf (asmfile, "r");
- CHARS (1);
- dbxout_type_index (char_type_node);
- fprintf (asmfile, ";0;%d;", TREE_UNSIGNED (type) ? 255 : 127);
- CHARS (7);
- }
+ stabstr_C (';');
+ stabstr_D (int_size_in_bytes (type));
+ stabstr_S (";0;");
break;
case BOOLEAN_TYPE:
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
- fputs ("@s", asmfile);
- CHARS (2);
- print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type));
- fputs (";-16;", asmfile);
- CHARS (4);
+ stabstr_S ("@s");
+ stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
+ stabstr_S (";-16;");
}
else /* Define as enumeral type (False, True) */
- {
- fprintf (asmfile, "eFalse:0,True:1,;");
- CHARS (17);
- }
- break;
-
- case FILE_TYPE:
- putc ('d', asmfile);
- CHARS (1);
- dbxout_type (TREE_TYPE (type), 0);
+ stabstr_S ("eFalse:0,True:1,;");
break;
case COMPLEX_TYPE:
@@ -1515,71 +1934,46 @@ dbxout_type (tree type, int full)
if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
{
- fputs ("R3;", asmfile);
- CHARS (3);
- print_wide_int (2 * int_size_in_bytes (TREE_TYPE (type)));
- fputs (";0;", asmfile);
- CHARS (3);
+ stabstr_S ("R3;");
+ stabstr_D (2 * int_size_in_bytes (TREE_TYPE (type)));
+ stabstr_S (";0;");
}
else
{
/* Output a complex integer type as a structure,
pending some other way to do it. */
- putc ('s', asmfile);
- CHARS (1);
- print_wide_int (int_size_in_bytes (type));
- fprintf (asmfile, "real:");
- CHARS (5);
+ stabstr_C ('s');
+ stabstr_D (int_size_in_bytes (type));
+ stabstr_S ("real:");
dbxout_type (TREE_TYPE (type), 0);
- fprintf (asmfile, ",0,%d;", TYPE_PRECISION (TREE_TYPE (type)));
- CHARS (7);
- fprintf (asmfile, "imag:");
- CHARS (5);
- dbxout_type (TREE_TYPE (type), 0);
- fprintf (asmfile, ",%d,%d;;", TYPE_PRECISION (TREE_TYPE (type)),
- TYPE_PRECISION (TREE_TYPE (type)));
- CHARS (10);
- }
- break;
+ stabstr_S (",0,");
+ stabstr_D (TYPE_PRECISION (TREE_TYPE (type)));
- case SET_TYPE:
- if (use_gnu_debug_info_extensions)
- {
- have_used_extensions = 1;
- fputs ("@s", asmfile);
- CHARS (2);
- print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type));
- putc (';', asmfile);
- CHARS (1);
-
- /* Check if a bitstring type, which in Chill is
- different from a [power]set. */
- if (TYPE_STRING_FLAG (type))
- {
- fprintf (asmfile, "@S;");
- CHARS (3);
- }
+ stabstr_S (";imag:");
+ dbxout_type (TREE_TYPE (type), 0);
+ stabstr_C (',');
+ stabstr_D (TYPE_PRECISION (TREE_TYPE (type)));
+ stabstr_C (',');
+ stabstr_D (TYPE_PRECISION (TREE_TYPE (type)));
+ stabstr_S (";;");
}
- putc ('S', asmfile);
- CHARS (1);
- dbxout_type (TYPE_DOMAIN (type), 0);
break;
case ARRAY_TYPE:
/* Make arrays of packed bits look like bitstrings for chill. */
if (TYPE_PACKED (type) && use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
- fputs ("@s", asmfile);
- CHARS (2);
- print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type));
- fprintf (asmfile, ";@S;S");
- CHARS (5);
+ stabstr_S ("@s");
+ stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
+ stabstr_S (";@S;S");
dbxout_type (TYPE_DOMAIN (type), 0);
break;
}
+ if (use_gnu_debug_info_extensions && vector_type)
+ stabstr_S ("@V;");
+
/* Output "a" followed by a range type definition
for the index type of the array
followed by a reference to the target-type.
@@ -1588,23 +1982,18 @@ dbxout_type (tree type, int full)
different from an array of characters. */
if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
- fprintf (asmfile, "@S;");
- CHARS (3);
+ stabstr_S ("@S;");
}
tem = TYPE_DOMAIN (type);
if (tem == NULL)
{
- fprintf (asmfile, "ar");
- CHARS (2);
+ stabstr_S ("ar");
dbxout_type_index (integer_type_node);
- fprintf (asmfile, ";0;-1;");
- CHARS (6);
+ stabstr_S (";0;-1;");
}
else
{
- fprintf (asmfile, "a");
- CHARS (1);
+ stabstr_C ('a');
dbxout_range_type (tem);
}
@@ -1615,12 +2004,7 @@ dbxout_type (tree type, int full)
case UNION_TYPE:
case QUAL_UNION_TYPE:
{
- int i, n_baseclasses = 0;
-
- if (TYPE_BINFO (type) != 0
- && TREE_CODE (TYPE_BINFO (type)) == TREE_VEC
- && TYPE_BINFO_BASETYPES (type) != 0)
- n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
+ tree binfo = TYPE_BINFO (type);
/* Output a structure type. We must use the same test here as we
use in the DBX_NO_XREFS case above. */
@@ -1639,93 +2023,83 @@ dbxout_type (tree type, int full)
If the type has a name, don't nest its definition within
another type's definition; instead, output an xref
and let the definition come when the name is defined. */
- fputs ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu", asmfile);
- CHARS (2);
-#if 0 /* This assertion is legitimately false in C++. */
- /* We shouldn't be outputting a reference to a type before its
- definition unless the type has a tag name.
- A typedef name without a tag name should be impossible. */
- if (TREE_CODE (TYPE_NAME (type)) != IDENTIFIER_NODE)
- abort ();
-#endif
+ stabstr_S ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu");
if (TYPE_NAME (type) != 0)
dbxout_type_name (type);
else
{
- fprintf (asmfile, "$$%d", anonymous_type_number++);
- CHARS (5);
+ stabstr_S ("$$");
+ stabstr_D (anonymous_type_number++);
}
- fprintf (asmfile, ":");
- CHARS (1);
+ stabstr_C (':');
typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
break;
}
/* Identify record or union, and print its size. */
- putc (((TREE_CODE (type) == RECORD_TYPE) ? 's' : 'u'), asmfile);
- CHARS (1);
- print_wide_int (int_size_in_bytes (type));
+ stabstr_C ((TREE_CODE (type) == RECORD_TYPE) ? 's' : 'u');
+ stabstr_D (int_size_in_bytes (type));
- if (use_gnu_debug_info_extensions)
+ if (binfo)
{
- if (n_baseclasses)
- {
- have_used_extensions = 1;
- fprintf (asmfile, "!%d,", n_baseclasses);
- CHARS (8);
- }
- }
- for (i = 0; i < n_baseclasses; i++)
- {
- tree binfo = TYPE_BINFO (type);
- tree child = BINFO_BASETYPE (binfo, i);
- tree access = (BINFO_BASEACCESSES (binfo)
- ? BINFO_BASEACCESS (binfo, i) : access_public_node);
-
+ int i;
+ tree child;
+ VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
+
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
- putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile);
- putc (access == access_public_node ? '2' :
- (access == access_protected_node ? '1' :'0'),
- asmfile);
- CHARS (2);
- if (TREE_VIA_VIRTUAL (child)
- && strcmp (lang_hooks.name, "GNU C++") == 0)
- /* For a virtual base, print the (negative) offset within
- the vtable where we must look to find the necessary
- adjustment. */
- print_wide_int (tree_low_cst (BINFO_VPTR_FIELD (child), 0)
- * BITS_PER_UNIT);
- else
- print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0)
- * BITS_PER_UNIT);
- putc (',', asmfile);
- CHARS (1);
- dbxout_type (BINFO_TYPE (child), 0);
- putc (';', asmfile);
- CHARS (1);
+ if (BINFO_N_BASE_BINFOS (binfo))
+ {
+ stabstr_C ('!');
+ stabstr_U (BINFO_N_BASE_BINFOS (binfo));
+ stabstr_C (',');
+ }
}
- else
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, child); i++)
{
- /* Print out the base class information with fields
- which have the same names at the types they hold. */
- dbxout_type_name (BINFO_TYPE (child));
- putc (':', asmfile);
- CHARS (1);
- dbxout_type (BINFO_TYPE (child), full);
- putc (',', asmfile);
- CHARS (1);
- print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0)
- * BITS_PER_UNIT);
- putc (',', asmfile);
- CHARS (1);
- print_wide_int (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)),
- 0)
- * BITS_PER_UNIT);
- putc (';', asmfile);
- CHARS (1);
+ tree access = (accesses ? VEC_index (tree, accesses, i)
+ : access_public_node);
+
+ if (use_gnu_debug_info_extensions)
+ {
+ stabstr_C (BINFO_VIRTUAL_P (child) ? '1' : '0');
+ stabstr_C (access == access_public_node ? '2' :
+ access == access_protected_node
+ ? '1' :'0');
+ if (BINFO_VIRTUAL_P (child)
+ && (strcmp (lang_hooks.name, "GNU C++") == 0
+ || strcmp (lang_hooks.name, "GNU Objective-C++") == 0))
+ /* For a virtual base, print the (negative)
+ offset within the vtable where we must look
+ to find the necessary adjustment. */
+ stabstr_D
+ (tree_low_cst (BINFO_VPTR_FIELD (child), 0)
+ * BITS_PER_UNIT);
+ else
+ stabstr_D (tree_low_cst (BINFO_OFFSET (child), 0)
+ * BITS_PER_UNIT);
+ stabstr_C (',');
+ dbxout_type (BINFO_TYPE (child), 0);
+ stabstr_C (';');
+ }
+ else
+ {
+ /* Print out the base class information with
+ fields which have the same names at the types
+ they hold. */
+ dbxout_type_name (BINFO_TYPE (child));
+ stabstr_C (':');
+ dbxout_type (BINFO_TYPE (child), full);
+ stabstr_C (',');
+ stabstr_D (tree_low_cst (BINFO_OFFSET (child), 0)
+ * BITS_PER_UNIT);
+ stabstr_C (',');
+ stabstr_D
+ (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)), 0)
+ * BITS_PER_UNIT);
+ stabstr_C (';');
+ }
}
}
}
@@ -1734,36 +2108,23 @@ dbxout_type (tree type, int full)
dbxout_type_fields (type);
if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE)
{
- have_used_extensions = 1;
dbxout_type_methods (type);
}
- putc (';', asmfile);
- CHARS (1);
+ stabstr_C (';');
if (use_gnu_debug_info_extensions && TREE_CODE (type) == RECORD_TYPE
/* Avoid the ~ if we don't really need it--it confuses dbx. */
&& TYPE_VFIELD (type))
{
- have_used_extensions = 1;
-
- /* Tell GDB+ that it may keep reading. */
- putc ('~', asmfile);
- CHARS (1);
/* We need to write out info about what field this class
uses as its "main" vtable pointer field, because if this
field is inherited from a base class, GDB cannot necessarily
figure out which field it's using in time. */
- if (TYPE_VFIELD (type))
- {
- putc ('%', asmfile);
- CHARS (1);
- dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0);
- }
-
- putc (';', asmfile);
- CHARS (1);
+ stabstr_S ("~%");
+ dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0);
+ stabstr_C (';');
}
break;
@@ -1777,66 +2138,58 @@ dbxout_type (tree type, int full)
&& !full)
|| !COMPLETE_TYPE_P (type))
{
- fprintf (asmfile, "xe");
- CHARS (2);
+ stabstr_S ("xe");
dbxout_type_name (type);
typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
- putc (':', asmfile);
- CHARS (1);
+ stabstr_C (':');
return;
}
if (use_gnu_debug_info_extensions
&& TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
{
- fprintf (asmfile, "@s%d;", TYPE_PRECISION (type));
- CHARS (5);
+ stabstr_S ("@s");
+ stabstr_D (TYPE_PRECISION (type));
+ stabstr_C (';');
}
- putc ('e', asmfile);
- CHARS (1);
+ stabstr_C ('e');
for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
{
- fprintf (asmfile, "%s:", IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
- CHARS (IDENTIFIER_LENGTH (TREE_PURPOSE (tem)) + 1);
+ stabstr_I (TREE_PURPOSE (tem));
+ stabstr_C (':');
+
if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0)
- print_wide_int (TREE_INT_CST_LOW (TREE_VALUE (tem)));
+ stabstr_D (TREE_INT_CST_LOW (TREE_VALUE (tem)));
else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1
&& (HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0)
- print_wide_int (TREE_INT_CST_LOW (TREE_VALUE (tem)));
+ stabstr_D (TREE_INT_CST_LOW (TREE_VALUE (tem)));
else
- print_int_cst_octal (TREE_VALUE (tem));
+ stabstr_O (TREE_VALUE (tem));
- putc (',', asmfile);
- CHARS (1);
+ stabstr_C (',');
if (TREE_CHAIN (tem) != 0)
CONTIN;
}
- putc (';', asmfile);
- CHARS (1);
+ stabstr_C (';');
break;
case POINTER_TYPE:
- putc ('*', asmfile);
- CHARS (1);
+ stabstr_C ('*');
dbxout_type (TREE_TYPE (type), 0);
break;
case METHOD_TYPE:
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
- putc ('#', asmfile);
- CHARS (1);
+ stabstr_C ('#');
/* Write the argument types out longhand. */
dbxout_type (TYPE_METHOD_BASETYPE (type), 0);
- putc (',', asmfile);
- CHARS (1);
+ stabstr_C (',');
dbxout_type (TREE_TYPE (type), 0);
dbxout_args (TYPE_ARG_TYPES (type));
- putc (';', asmfile);
- CHARS (1);
+ stabstr_C (';');
}
else
/* Treat it as a function type. */
@@ -1846,12 +2199,9 @@ dbxout_type (tree type, int full)
case OFFSET_TYPE:
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
- putc ('@', asmfile);
- CHARS (1);
+ stabstr_C ('@');
dbxout_type (TYPE_OFFSET_BASETYPE (type), 0);
- putc (',', asmfile);
- CHARS (1);
+ stabstr_C (',');
dbxout_type (TREE_TYPE (type), 0);
}
else
@@ -1861,20 +2211,21 @@ dbxout_type (tree type, int full)
case REFERENCE_TYPE:
if (use_gnu_debug_info_extensions)
- have_used_extensions = 1;
- putc (use_gnu_debug_info_extensions ? '&' : '*', asmfile);
- CHARS (1);
+ {
+ stabstr_C ('&');
+ }
+ else
+ stabstr_C ('*');
dbxout_type (TREE_TYPE (type), 0);
break;
case FUNCTION_TYPE:
- putc ('f', asmfile);
- CHARS (1);
+ stabstr_C ('f');
dbxout_type (TREE_TYPE (type), 0);
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -1902,145 +2253,199 @@ print_int_cst_bounds_in_octal_p (tree type)
&& TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
&& (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
|| ((TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
- && TREE_UNSIGNED (type))
+ && TYPE_UNSIGNED (type))
|| TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
|| (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
- && TREE_UNSIGNED (type))))
+ && TYPE_UNSIGNED (type))))
return TRUE;
else
return FALSE;
}
-/* Print the value of integer constant C, in octal,
- handling double precision. */
+/* Output the name of type TYPE, with no punctuation.
+ Such names can be set up either by typedef declarations
+ or by struct, enum and union tags. */
static void
-print_int_cst_octal (tree c)
+dbxout_type_name (tree type)
{
- unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (c);
- unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (c);
- int excess = (3 - (HOST_BITS_PER_WIDE_INT % 3));
- unsigned int width = TYPE_PRECISION (TREE_TYPE (c));
+ tree t = TYPE_NAME (type);
+
+ gcc_assert (t);
+ switch (TREE_CODE (t))
+ {
+ case IDENTIFIER_NODE:
+ break;
+ case TYPE_DECL:
+ t = DECL_NAME (t);
+ break;
+ default:
+ gcc_unreachable ();
+ }
- /* GDB wants constants with no extra leading "1" bits, so
- we need to remove any sign-extension that might be
- present. */
- if (width == HOST_BITS_PER_WIDE_INT * 2)
- ;
- else if (width > HOST_BITS_PER_WIDE_INT)
- high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
- else if (width == HOST_BITS_PER_WIDE_INT)
- high = 0;
- else
- high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
+ stabstr_I (t);
+}
+
+/* Output leading leading struct or class names needed for qualifying
+ type whose scope is limited to a struct or class. */
- fprintf (asmfile, "0");
- CHARS (1);
+static void
+dbxout_class_name_qualifiers (tree decl)
+{
+ tree context = decl_type_context (decl);
- if (excess == 3)
- {
- print_octal (high, HOST_BITS_PER_WIDE_INT / 3);
- print_octal (low, HOST_BITS_PER_WIDE_INT / 3);
- }
- else
+ if (context != NULL_TREE
+ && TREE_CODE(context) == RECORD_TYPE
+ && TYPE_NAME (context) != 0
+ && (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
+ || (DECL_NAME (TYPE_NAME (context)) != 0)))
{
- unsigned HOST_WIDE_INT beg = high >> excess;
- unsigned HOST_WIDE_INT middle
- = ((high & (((HOST_WIDE_INT) 1 << excess) - 1)) << (3 - excess)
- | (low >> (HOST_BITS_PER_WIDE_INT / 3 * 3)));
- unsigned HOST_WIDE_INT end
- = low & (((unsigned HOST_WIDE_INT) 1
- << (HOST_BITS_PER_WIDE_INT / 3 * 3))
- - 1);
-
- fprintf (asmfile, "%o%01o", (int) beg, (int) middle);
- CHARS (2);
- print_octal (end, HOST_BITS_PER_WIDE_INT / 3);
+ tree name = TYPE_NAME (context);
+
+ if (TREE_CODE (name) == TYPE_DECL)
+ {
+ dbxout_class_name_qualifiers (name);
+ name = DECL_NAME (name);
+ }
+ stabstr_I (name);
+ stabstr_S ("::");
}
}
+
+/* This is a specialized subset of expand_expr for use by dbxout_symbol in
+ evaluating DECL_VALUE_EXPR. In particular, we stop if we find decls that
+ havn't been expanded, or if the expression is getting so complex we won't
+ be able to represent it in stabs anyway. Returns NULL on failure. */
-static void
-print_octal (unsigned HOST_WIDE_INT value, int digits)
+static rtx
+dbxout_expand_expr (tree expr)
{
- int i;
+ switch (TREE_CODE (expr))
+ {
+ case VAR_DECL:
+ case PARM_DECL:
+ if (DECL_HAS_VALUE_EXPR_P (expr))
+ return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
+ /* FALLTHRU */
- for (i = digits - 1; i >= 0; i--)
- fprintf (asmfile, "%01o", (int) ((value >> (3 * i)) & 7));
+ case CONST_DECL:
+ case RESULT_DECL:
+ return DECL_RTL_IF_SET (expr);
- CHARS (digits);
-}
+ case INTEGER_CST:
+ return expand_expr (expr, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
-/* Output C in decimal while adjusting the number of digits written. */
+ case COMPONENT_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case BIT_FIELD_REF:
+ {
+ enum machine_mode mode;
+ HOST_WIDE_INT bitsize, bitpos;
+ tree offset, tem;
+ int volatilep = 0, unsignedp = 0;
+ rtx x;
+
+ tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
+ &mode, &unsignedp, &volatilep, true);
+
+ x = dbxout_expand_expr (tem);
+ if (x == NULL || !MEM_P (x))
+ return NULL;
+ if (offset != NULL)
+ {
+ if (!host_integerp (offset, 0))
+ return NULL;
+ x = adjust_address_nv (x, mode, tree_low_cst (offset, 0));
+ }
+ if (bitpos != 0)
+ x = adjust_address_nv (x, mode, bitpos / BITS_PER_UNIT);
-static void
-print_wide_int (HOST_WIDE_INT c)
-{
- int digs = 0;
+ return x;
+ }
- fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, c);
+ default:
+ return NULL;
+ }
+}
- if (c < 0)
- digs++, c = -c;
+/* Helper function for output_used_types. Queue one entry from the
+ used types hash to be output. */
- while (c > 0)
- c /= 10; digs++;
+static int
+output_used_types_helper (void **slot, void *data)
+{
+ tree type = *slot;
+ VEC(tree, heap) **types_p = data;
- CHARS (digs);
+ if ((TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
+ && TYPE_STUB_DECL (type)
+ && DECL_P (TYPE_STUB_DECL (type))
+ && ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
+ VEC_quick_push (tree, *types_p, TYPE_STUB_DECL (type));
+ else if (TYPE_NAME (type)
+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+ VEC_quick_push (tree, *types_p, TYPE_NAME (type));
+
+ return 1;
}
-/* Output the name of type TYPE, with no punctuation.
- Such names can be set up either by typedef declarations
- or by struct, enum and union tags. */
+/* This is a qsort callback which sorts types and declarations into a
+ predictable order (types, then declarations, sorted by UID
+ within). */
-static void
-dbxout_type_name (tree type)
+static int
+output_types_sort (const void *pa, const void *pb)
{
- tree t;
- if (TYPE_NAME (type) == 0)
- abort ();
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
+ const tree lhs = *((const tree *)pa);
+ const tree rhs = *((const tree *)pb);
+
+ if (TYPE_P (lhs))
{
- t = TYPE_NAME (type);
+ if (TYPE_P (rhs))
+ return TYPE_UID (lhs) - TYPE_UID (rhs);
+ else
+ return 1;
}
- else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+ else
{
- t = DECL_NAME (TYPE_NAME (type));
+ if (TYPE_P (rhs))
+ return -1;
+ else
+ return DECL_UID (lhs) - DECL_UID (rhs);
}
- else
- abort ();
-
- fprintf (asmfile, "%s", IDENTIFIER_POINTER (t));
- CHARS (IDENTIFIER_LENGTH (t));
}
-/* Output leading leading struct or class names needed for qualifying
- type whose scope is limited to a struct or class. */
+
+/* Force all types used by this function to be output in debug
+ information. */
static void
-dbxout_class_name_qualifiers (tree decl)
+output_used_types (void)
{
- tree context = decl_type_context (decl);
-
- if (context != NULL_TREE
- && TREE_CODE(context) == RECORD_TYPE
- && TYPE_NAME (context) != 0
- && (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
- || (DECL_NAME (TYPE_NAME (context)) != 0)))
+ if (cfun && cfun->used_types_hash)
{
- tree name = TYPE_NAME (context);
+ VEC(tree, heap) *types;
+ int i;
+ tree type;
- emit_pending_bincls_if_required ();
+ types = VEC_alloc (tree, heap, htab_elements (cfun->used_types_hash));
+ htab_traverse (cfun->used_types_hash, output_used_types_helper, &types);
- if (TREE_CODE (name) == TYPE_DECL)
- {
- dbxout_class_name_qualifiers (name);
- name = DECL_NAME (name);
- }
- fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
- CHARS (IDENTIFIER_LENGTH (name) + 2);
+ /* Sort by UID to prevent dependence on hash table ordering. */
+ qsort (VEC_address (tree, types), VEC_length (tree, types),
+ sizeof (tree), output_types_sort);
+
+ for (i = 0; VEC_iterate (tree, types, i, type); i++)
+ debug_queue_symbol (type);
+
+ VEC_free (tree, heap, types);
}
}
-
+
/* Output a .stabs for the symbol defined by DECL,
which must be a ..._DECL node in the normal namespace.
It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL.
@@ -2053,6 +2458,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
tree type = TREE_TYPE (decl);
tree context = NULL_TREE;
int result = 0;
+ rtx decl_rtl;
/* "Intercept" dbxout_symbol() calls like we do all debug_hooks. */
++debug_nesting;
@@ -2064,22 +2470,30 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
DBXOUT_DECR_NESTING_AND_RETURN (0);
/* If we are to generate only the symbols actually used then such
- symbol nodees are flagged with TREE_USED. Ignore any that
+ symbol nodes are flagged with TREE_USED. Ignore any that
aren't flaged as TREE_USED. */
+ if (flag_debug_only_used_symbols
+ && (!TREE_USED (decl)
+ && (TREE_CODE (decl) != VAR_DECL || !DECL_INITIAL (decl))))
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
+
+ /* If dbxout_init has not yet run, queue this symbol for later. */
+ if (!typevec)
+ {
+ preinit_symbols = tree_cons (0, decl, preinit_symbols);
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
+ }
+
if (flag_debug_only_used_symbols)
{
tree t;
- if (!TREE_USED (decl)
- && (TREE_CODE (decl) != VAR_DECL || !DECL_INITIAL (decl)))
- DBXOUT_DECR_NESTING_AND_RETURN (0);
-
/* We now have a used symbol. We need to generate the info for
the symbol's type in addition to the symbol itself. These
type symbols are queued to be generated after were done with
- the symbol itself (done because the symbol's info is generated
- with fprintf's, etc. as it determines what's needed).
+ the symbol itself (otherwise they would fight over the
+ stabstr obstack).
Note, because the TREE_TYPE(type) might be something like a
pointer to a named type we need to look for the first name
@@ -2096,38 +2510,32 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
a different name. In that case we also want to output
that. */
- if ((TREE_CODE (t) == RECORD_TYPE
+ if (TREE_CODE (t) == RECORD_TYPE
|| TREE_CODE (t) == UNION_TYPE
|| TREE_CODE (t) == QUAL_UNION_TYPE
|| TREE_CODE (t) == ENUMERAL_TYPE)
- && TYPE_STUB_DECL (t)
- && TYPE_STUB_DECL (t) != decl
- && TREE_CODE_CLASS (TREE_CODE (TYPE_STUB_DECL (t))) == 'd'
- && ! DECL_IGNORED_P (TYPE_STUB_DECL (t)))
{
- debug_queue_symbol (TYPE_STUB_DECL (t));
- if (TYPE_NAME (t)
- && TYPE_NAME (t) != TYPE_STUB_DECL (t)
- && TYPE_NAME (t) != decl
- && TREE_CODE_CLASS (TREE_CODE (TYPE_NAME (t))) == 'd')
- debug_queue_symbol (TYPE_NAME (t));
- }
+ if (TYPE_STUB_DECL (t)
+ && TYPE_STUB_DECL (t) != decl
+ && DECL_P (TYPE_STUB_DECL (t))
+ && ! DECL_IGNORED_P (TYPE_STUB_DECL (t)))
+ {
+ debug_queue_symbol (TYPE_STUB_DECL (t));
+ if (TYPE_NAME (t)
+ && TYPE_NAME (t) != TYPE_STUB_DECL (t)
+ && TYPE_NAME (t) != decl
+ && DECL_P (TYPE_NAME (t)))
+ debug_queue_symbol (TYPE_NAME (t));
+ }
+ }
else if (TYPE_NAME (t)
&& TYPE_NAME (t) != decl
- && TREE_CODE_CLASS (TREE_CODE (TYPE_NAME (t))) == 'd')
+ && DECL_P (TYPE_NAME (t)))
debug_queue_symbol (TYPE_NAME (t));
}
emit_pending_bincls_if_required ();
- dbxout_prepare_symbol (decl);
-
- /* The output will always start with the symbol name,
- so always count that in the length-output-so-far. */
-
- if (DECL_NAME (decl) != 0)
- current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (decl));
-
switch (TREE_CODE (decl))
{
case CONST_DECL:
@@ -2135,7 +2543,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
break;
case FUNCTION_DECL:
- if (DECL_RTL (decl) == 0)
+ decl_rtl = DECL_RTL_IF_SET (decl);
+ if (!decl_rtl)
DBXOUT_DECR_NESTING_AND_RETURN (0);
if (DECL_EXTERNAL (decl))
break;
@@ -2143,18 +2552,20 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
context = decl_function_context (decl);
if (context == current_function_decl)
break;
- if (GET_CODE (DECL_RTL (decl)) != MEM
- || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
+ /* Don't mention an inline instance of a nested function. */
+ if (context && DECL_FROM_INLINE (decl))
+ break;
+ if (!MEM_P (decl_rtl)
+ || GET_CODE (XEXP (decl_rtl, 0)) != SYMBOL_REF)
break;
- FORCE_TEXT;
- fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
- TREE_PUBLIC (decl) ? 'F' : 'f');
- result = 1;
+ if (flag_debug_only_used_symbols)
+ output_used_types ();
- current_sym_code = N_FUN;
- current_sym_addr = XEXP (DECL_RTL (decl), 0);
+ dbxout_begin_complex_stabs ();
+ stabstr_I (DECL_ASSEMBLER_NAME (decl));
+ stabstr_S (TREE_PUBLIC (decl) ? ":F" : ":f");
+ result = 1;
if (TREE_TYPE (type))
dbxout_type (TREE_TYPE (type), 0);
@@ -2165,11 +2576,14 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
mention the containing function name
as well as (since dbx wants it) our own assembler-name. */
if (context != 0)
- fprintf (asmfile, ",%s,%s",
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
- IDENTIFIER_POINTER (DECL_NAME (context)));
+ {
+ stabstr_C (',');
+ stabstr_I (DECL_ASSEMBLER_NAME (decl));
+ stabstr_C (',');
+ stabstr_I (DECL_NAME (context));
+ }
- dbxout_finish_symbol (decl);
+ dbxout_finish_complex_stabs (decl, N_FUN, XEXP (decl_rtl, 0), 0, 0);
break;
case TYPE_DECL:
@@ -2178,6 +2592,20 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl))
DBXOUT_DECR_NESTING_AND_RETURN (0);
+ /* Don't output typedefs for types with magic type numbers (XCOFF). */
+#ifdef DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER
+ {
+ int fundamental_type_number =
+ DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER (decl);
+
+ if (fundamental_type_number != 0)
+ {
+ TREE_ASM_WRITTEN (decl) = 1;
+ TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = fundamental_type_number;
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
+ }
+ }
+#endif
FORCE_TEXT;
result = 1;
{
@@ -2197,7 +2625,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
&& TYPE_NAME (type) == decl
- && !(use_gnu_debug_info_extensions && have_used_extensions)
+ && !use_gnu_debug_info_extensions
&& !TREE_ASM_WRITTEN (TYPE_NAME (type))
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
@@ -2213,28 +2641,23 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
- current_sym_code = DBX_TYPE_DECL_STABS_CODE;
- current_sym_value = 0;
- current_sym_addr = 0;
- current_sym_nchars = 2 + IDENTIFIER_LENGTH (name);
-
- fprintf (asmfile, "%s\"%s:T", ASM_STABS_OP,
- IDENTIFIER_POINTER (name));
+ dbxout_begin_complex_stabs ();
+ stabstr_I (name);
+ stabstr_S (":T");
dbxout_type (type, 1);
- dbxout_finish_symbol (NULL_TREE);
+ dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE,
+ 0, 0, 0);
}
- /* Output .stabs (or whatever) and leading double quote. */
- fprintf (asmfile, "%s\"", ASM_STABS_OP);
+ dbxout_begin_complex_stabs ();
+ /* Output leading class/struct qualifiers. */
if (use_gnu_debug_info_extensions)
- {
- /* Output leading class/struct qualifiers. */
- dbxout_class_name_qualifiers (decl);
- }
+ dbxout_class_name_qualifiers (decl);
/* Output typedef name. */
- fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (decl)));
+ stabstr_I (DECL_NAME (decl));
+ stabstr_C (':');
/* Short cut way to output a tag also. */
if ((TREE_CODE (type) == RECORD_TYPE
@@ -2245,22 +2668,17 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
from explicit ones that might be found in C. */
&& DECL_ARTIFICIAL (decl))
{
- if (use_gnu_debug_info_extensions && have_used_extensions)
+ if (use_gnu_debug_info_extensions)
{
- putc ('T', asmfile);
+ stabstr_C ('T');
TREE_ASM_WRITTEN (TYPE_NAME (type)) = 1;
}
-#if 0 /* Now we generate the tag for this case up above. */
- else
- tag_needed = 1;
-#endif
}
- putc ('t', asmfile);
- current_sym_code = DBX_TYPE_DECL_STABS_CODE;
-
+ stabstr_C ('t');
dbxout_type (type, 1);
- dbxout_finish_symbol (decl);
+ dbxout_finish_complex_stabs (decl, DBX_TYPE_DECL_STABS_CODE,
+ 0, 0, 0);
did_output = 1;
}
@@ -2282,33 +2700,26 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
- current_sym_code = DBX_TYPE_DECL_STABS_CODE;
- current_sym_value = 0;
- current_sym_addr = 0;
- current_sym_nchars = 2 + IDENTIFIER_LENGTH (name);
-
- fprintf (asmfile, "%s\"%s:T", ASM_STABS_OP,
- IDENTIFIER_POINTER (name));
+ dbxout_begin_complex_stabs ();
+ stabstr_I (name);
+ stabstr_S (":T");
dbxout_type (type, 1);
- dbxout_finish_symbol (NULL_TREE);
+ dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE, 0, 0, 0);
did_output = 1;
}
- /* If an enum type has no name, it cannot be referred to,
- but we must output it anyway, since the enumeration constants
- can be referred to. */
+ /* If an enum type has no name, it cannot be referred to, but
+ we must output it anyway, to record the enumeration
+ constants. */
+
if (!did_output && TREE_CODE (type) == ENUMERAL_TYPE)
{
- current_sym_code = DBX_TYPE_DECL_STABS_CODE;
- current_sym_value = 0;
- current_sym_addr = 0;
- current_sym_nchars = 2;
-
+ dbxout_begin_complex_stabs ();
/* Some debuggers fail when given NULL names, so give this a
- harmless name of ` '. */
- fprintf (asmfile, "%s\" :T", ASM_STABS_OP);
+ harmless name of " " (Why not "(anon)"?). */
+ stabstr_S (" :T");
dbxout_type (type, 1);
- dbxout_finish_symbol (NULL_TREE);
+ dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE, 0, 0, 0);
}
/* Prevent duplicate output of a typedef. */
@@ -2319,58 +2730,59 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
case PARM_DECL:
/* Parm decls go in their own separate chains
and are output by dbxout_reg_parms and dbxout_parms. */
- abort ();
+ gcc_unreachable ();
case RESULT_DECL:
- /* Named return value, treat like a VAR_DECL. */
case VAR_DECL:
- if (! DECL_RTL_SET_P (decl))
- DBXOUT_DECR_NESTING_AND_RETURN (0);
/* Don't mention a variable that is external.
Let the file that defines it describe it. */
if (DECL_EXTERNAL (decl))
break;
/* If the variable is really a constant
- and not written in memory, inform the debugger. */
+ and not written in memory, inform the debugger.
+
+ ??? Why do we skip emitting the type and location in this case? */
if (TREE_STATIC (decl) && TREE_READONLY (decl)
&& DECL_INITIAL (decl) != 0
&& host_integerp (DECL_INITIAL (decl), 0)
&& ! TREE_ASM_WRITTEN (decl)
&& (DECL_CONTEXT (decl) == NULL_TREE
- || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK))
+ || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
+ || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+ && TREE_PUBLIC (decl) == 0)
{
- if (TREE_PUBLIC (decl) == 0)
- {
- /* The sun4 assembler does not grok this. */
- const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ /* The sun4 assembler does not grok this. */
- if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE
- || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
- {
- HOST_WIDE_INT ival = tree_low_cst (DECL_INITIAL (decl), 0);
- fprintf (asmfile, "%s\"%s:c=i" HOST_WIDE_INT_PRINT_DEC
- "\",0x%x,0,0,0\n",
- ASM_STABS_OP, name, ival, N_LSYM);
- DBXOUT_DECR_NESTING;
- return 1;
- }
- else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE)
- {
- /* Don't know how to do this yet. */
- }
- break;
+ if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ {
+ HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl));
+
+ dbxout_begin_complex_stabs ();
+ dbxout_symbol_name (decl, NULL, 'c');
+ stabstr_S ("=i");
+ stabstr_D (ival);
+ dbxout_finish_complex_stabs (0, N_LSYM, 0, 0, 0);
+ DBXOUT_DECR_NESTING;
+ return 1;
}
- /* else it is something we handle like a normal variable. */
+ else
+ break;
}
+ /* else it is something we handle like a normal variable. */
+
+ decl_rtl = dbxout_expand_expr (decl);
+ if (!decl_rtl)
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
- SET_DECL_RTL (decl, eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
+ decl_rtl = eliminate_regs (decl_rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
if (current_function_uses_only_leaf_regs)
- leaf_renumber_regs_insn (DECL_RTL (decl));
+ leaf_renumber_regs_insn (decl_rtl);
#endif
- result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
+ result = dbxout_symbol_location (decl, type, 0, decl_rtl);
break;
default:
@@ -2390,10 +2802,11 @@ static int
dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
{
int letter = 0;
+ STAB_CODE_TYPE code;
+ rtx addr = 0;
+ int number = 0;
int regno = -1;
- emit_pending_bincls_if_required ();
-
/* Don't mention a variable at all
if it was completely optimized into nothingness.
@@ -2406,14 +2819,14 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
while (GET_CODE (value) == SUBREG)
value = SUBREG_REG (value);
- if (GET_CODE (value) == REG)
+ if (REG_P (value))
{
if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return 0;
}
home = alter_subreg (&home);
}
- if (GET_CODE (home) == REG)
+ if (REG_P (home))
{
regno = REGNO (home);
if (regno >= FIRST_PSEUDO_REGISTER)
@@ -2433,17 +2846,16 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
no letter at all, and N_LSYM, for auto variable,
r and N_RSYM for register variable. */
- if (GET_CODE (home) == MEM
- && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
+ if (MEM_P (home) && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
{
if (TREE_PUBLIC (decl))
{
letter = 'G';
- current_sym_code = N_GSYM;
+ code = N_GSYM;
}
else
{
- current_sym_addr = XEXP (home, 0);
+ addr = XEXP (home, 0);
letter = decl_function_context (decl) ? 'V' : 'S';
@@ -2452,23 +2864,23 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
dumped into a constant pool. Alternatively, the symbol
in the constant pool might be referenced by a different
symbol. */
- if (GET_CODE (current_sym_addr) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (current_sym_addr))
+ if (GET_CODE (addr) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (addr))
{
bool marked;
- rtx tmp = get_pool_constant_mark (current_sym_addr, &marked);
+ rtx tmp = get_pool_constant_mark (addr, &marked);
if (GET_CODE (tmp) == SYMBOL_REF)
{
- current_sym_addr = tmp;
- if (CONSTANT_POOL_ADDRESS_P (current_sym_addr))
- get_pool_constant_mark (current_sym_addr, &marked);
+ addr = tmp;
+ if (CONSTANT_POOL_ADDRESS_P (addr))
+ get_pool_constant_mark (addr, &marked);
else
marked = true;
}
else if (GET_CODE (tmp) == LABEL_REF)
{
- current_sym_addr = tmp;
+ addr = tmp;
marked = true;
}
@@ -2485,30 +2897,30 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
if (DECL_INITIAL (decl) == 0
|| (!strcmp (lang_hooks.name, "GNU C++")
&& DECL_INITIAL (decl) == error_mark_node))
- current_sym_code = N_LCSYM;
+ code = N_LCSYM;
else if (DECL_IN_TEXT_SECTION (decl))
/* This is not quite right, but it's the closest
of all the codes that Unix defines. */
- current_sym_code = DBX_STATIC_CONST_VAR_CODE;
+ code = DBX_STATIC_CONST_VAR_CODE;
else
{
/* Ultrix `as' seems to need this. */
#ifdef DBX_STATIC_STAB_DATA_SECTION
- data_section ();
+ switch_to_section (data_section);
#endif
- current_sym_code = N_STSYM;
+ code = N_STSYM;
}
}
}
else if (regno >= 0)
{
letter = 'r';
- current_sym_code = N_RSYM;
- current_sym_value = DBX_REGISTER_NUMBER (regno);
+ code = N_RSYM;
+ number = DBX_REGISTER_NUMBER (regno);
}
- else if (GET_CODE (home) == MEM
- && (GET_CODE (XEXP (home, 0)) == MEM
- || (GET_CODE (XEXP (home, 0)) == REG
+ else if (MEM_P (home)
+ && (MEM_P (XEXP (home, 0))
+ || (REG_P (XEXP (home, 0))
&& REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
&& REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
@@ -2520,24 +2932,22 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
then it means the object is variable-sized and address through
that register or stack slot. DBX has no way to represent this
so all we can do is output the variable as a pointer.
- If it's not a parameter, ignore it.
- (VAR_DECLs like this can be made by integrate.c.) */
+ If it's not a parameter, ignore it. */
{
- if (GET_CODE (XEXP (home, 0)) == REG)
+ if (REG_P (XEXP (home, 0)))
{
letter = 'r';
- current_sym_code = N_RSYM;
+ code = N_RSYM;
if (REGNO (XEXP (home, 0)) >= FIRST_PSEUDO_REGISTER)
return 0;
- current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (home, 0)));
+ number = DBX_REGISTER_NUMBER (REGNO (XEXP (home, 0)));
}
else
{
- current_sym_code = N_LSYM;
+ code = N_LSYM;
/* RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))).
We want the value of that CONST_INT. */
- current_sym_value
- = DEBUGGER_AUTO_OFFSET (XEXP (XEXP (home, 0), 0));
+ number = DEBUGGER_AUTO_OFFSET (XEXP (XEXP (home, 0), 0));
}
/* Effectively do build_pointer_type, but don't cache this type,
@@ -2547,22 +2957,22 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
type = make_node (POINTER_TYPE);
TREE_TYPE (type) = TREE_TYPE (decl);
}
- else if (GET_CODE (home) == MEM
- && GET_CODE (XEXP (home, 0)) == REG)
+ else if (MEM_P (home)
+ && REG_P (XEXP (home, 0)))
{
- current_sym_code = N_LSYM;
- current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
+ code = N_LSYM;
+ number = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
}
- else if (GET_CODE (home) == MEM
+ else if (MEM_P (home)
&& GET_CODE (XEXP (home, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
{
- current_sym_code = N_LSYM;
+ code = N_LSYM;
/* RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
We want the value of that CONST_INT. */
- current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
+ number = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
}
- else if (GET_CODE (home) == MEM
+ else if (MEM_P (home)
&& GET_CODE (XEXP (home, 0)) == CONST)
{
/* Handle an obscure case which can arise when optimizing and
@@ -2576,9 +2986,9 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
variable, thereby avoiding the need for a register. In such
cases we're forced to lie to debuggers and tell them that
this variable was itself `static'. */
- current_sym_code = N_LCSYM;
+ code = N_LCSYM;
letter = 'V';
- current_sym_addr = XEXP (XEXP (home, 0), 0);
+ addr = XEXP (XEXP (home, 0), 0);
}
else if (GET_CODE (home) == CONCAT)
{
@@ -2599,8 +3009,6 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
else
dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 0));
- dbxout_prepare_symbol (decl);
-
if (WORDS_BIG_ENDIAN)
dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 1));
else
@@ -2614,18 +3022,20 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
return 0;
/* Ok, start a symtab entry and output the variable name. */
+ emit_pending_bincls_if_required ();
FORCE_TEXT;
#ifdef DBX_STATIC_BLOCK_START
- DBX_STATIC_BLOCK_START (asmfile, current_sym_code);
+ DBX_STATIC_BLOCK_START (asm_out_file, code);
#endif
+ dbxout_begin_complex_stabs_noforcetext ();
dbxout_symbol_name (decl, suffix, letter);
dbxout_type (type, 0);
- dbxout_finish_symbol (decl);
+ dbxout_finish_complex_stabs (decl, code, addr, 0, number);
#ifdef DBX_STATIC_BLOCK_END
- DBX_STATIC_BLOCK_END (asmfile, current_sym_code);
+ DBX_STATIC_BLOCK_END (asm_out_file, code);
#endif
return 1;
}
@@ -2636,7 +3046,7 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
static void
dbxout_symbol_name (tree decl, const char *suffix, int letter)
{
- const char *name;
+ tree name;
if (DECL_CONTEXT (decl)
&& (TYPE_P (DECL_CONTEXT (decl))
@@ -2645,56 +3055,22 @@ dbxout_symbol_name (tree decl, const char *suffix, int letter)
or a namespace member, we must put out the mangled name instead of the
DECL_NAME. Note also that static member (variable) names DO NOT begin
with underscores in .stabs directives. */
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = DECL_ASSEMBLER_NAME (decl);
else
/* ...but if we're function-local, we don't want to include the junk
added by ASM_FORMAT_PRIVATE_NAME. */
- name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ name = DECL_NAME (decl);
- if (name == 0)
- name = "(anon)";
- fprintf (asmfile, "%s\"%s%s:", ASM_STABS_OP, name,
- (suffix ? suffix : ""));
+ if (name)
+ stabstr_I (name);
+ else
+ stabstr_S ("(anon)");
+ if (suffix)
+ stabstr_S (suffix);
+ stabstr_C (':');
if (letter)
- putc (letter, asmfile);
-}
-
-static void
-dbxout_prepare_symbol (tree decl ATTRIBUTE_UNUSED)
-{
-#ifdef WINNING_GDB
- const char *filename = DECL_SOURCE_FILE (decl);
-
- dbxout_source_file (asmfile, filename);
-#endif
-
- /* Initialize variables used to communicate each symbol's debug
- information to dbxout_finish_symbol with zeroes. */
-
- /* Cast avoids warning in old compilers. */
- current_sym_code = (STAB_CODE_TYPE) 0;
- current_sym_value = 0;
- current_sym_addr = 0;
-}
-
-static void
-dbxout_finish_symbol (tree sym)
-{
-#ifdef DBX_FINISH_SYMBOL
- DBX_FINISH_SYMBOL (sym);
-#else
- int line = 0;
- if (use_gnu_debug_info_extensions && sym != 0)
- line = DECL_SOURCE_LINE (sym);
-
- fprintf (asmfile, "\",%d,0,%d,", current_sym_code, line);
- if (current_sym_addr)
- output_addr_const (asmfile, current_sym_addr);
- else
- fprintf (asmfile, "%d", current_sym_value);
- putc ('\n', asmfile);
-#endif
+ stabstr_C (letter);
}
/* Output definitions of all the decls in a chain. Return nonzero if
@@ -2728,13 +3104,18 @@ void
dbxout_parms (tree parms)
{
++debug_nesting;
-
emit_pending_bincls_if_required ();
for (; parms; parms = TREE_CHAIN (parms))
- if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+ if (DECL_NAME (parms)
+ && TREE_TYPE (parms) != error_mark_node
+ && DECL_RTL_SET_P (parms)
+ && DECL_INCOMING_RTL (parms))
{
- dbxout_prepare_symbol (parms);
+ tree eff_type;
+ char letter;
+ STAB_CODE_TYPE code;
+ int number;
/* Perform any necessary register eliminations on the parameter's rtl,
so that the debugging output will be accurate. */
@@ -2751,107 +3132,63 @@ dbxout_parms (tree parms)
if (PARM_PASSED_IN_MEMORY (parms))
{
- rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
+ rtx inrtl = XEXP (DECL_INCOMING_RTL (parms), 0);
/* ??? Here we assume that the parm address is indexed
off the frame pointer or arg pointer.
If that is not true, we produce meaningless results,
but do not crash. */
- if (GET_CODE (addr) == PLUS
- && GET_CODE (XEXP (addr, 1)) == CONST_INT)
- current_sym_value = INTVAL (XEXP (addr, 1));
- else
- current_sym_value = 0;
-
- current_sym_code = N_PSYM;
- current_sym_addr = 0;
-
- FORCE_TEXT;
- if (DECL_NAME (parms))
- {
- current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));
-
- fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_NAME (parms)),
- DBX_MEMPARM_STABS_LETTER);
- }
+ if (GET_CODE (inrtl) == PLUS
+ && GET_CODE (XEXP (inrtl, 1)) == CONST_INT)
+ number = INTVAL (XEXP (inrtl, 1));
else
- {
- current_sym_nchars = 8;
- fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP,
- DBX_MEMPARM_STABS_LETTER);
- }
-
- /* It is quite tempting to use:
-
- dbxout_type (TREE_TYPE (parms), 0);
-
- as the next statement, rather than using DECL_ARG_TYPE(), so
- that gcc reports the actual type of the parameter, rather
- than the promoted type. This certainly makes GDB's life
- easier, at least for some ports. The change is a bad idea
- however, since GDB expects to be able access the type without
- performing any conversions. So for example, if we were
- passing a float to an unprototyped function, gcc will store a
- double on the stack, but if we emit a stab saying the type is a
- float, then gdb will only read in a single value, and this will
- produce an erroneous value. */
- dbxout_type (DECL_ARG_TYPE (parms), 0);
- current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
- dbxout_finish_symbol (parms);
+ number = 0;
+
+ code = N_PSYM;
+ number = DEBUGGER_ARG_OFFSET (number, inrtl);
+ letter = 'p';
+
+ /* It is quite tempting to use TREE_TYPE (parms) instead
+ of DECL_ARG_TYPE (parms) for the eff_type, so that gcc
+ reports the actual type of the parameter, rather than
+ the promoted type. This certainly makes GDB's life
+ easier, at least for some ports. The change is a bad
+ idea however, since GDB expects to be able access the
+ type without performing any conversions. So for
+ example, if we were passing a float to an unprototyped
+ function, gcc will store a double on the stack, but if
+ we emit a stab saying the type is a float, then gdb
+ will only read in a single value, and this will produce
+ an erroneous value. */
+ eff_type = DECL_ARG_TYPE (parms);
}
- else if (GET_CODE (DECL_RTL (parms)) == REG)
+ else if (REG_P (DECL_RTL (parms)))
{
rtx best_rtl;
- char regparm_letter;
- tree parm_type;
- /* Parm passed in registers and lives in registers or nowhere. */
- current_sym_code = DBX_REGPARM_STABS_CODE;
- regparm_letter = DBX_REGPARM_STABS_LETTER;
- current_sym_addr = 0;
-
- /* If parm lives in a register, use that register;
- pretend the parm was passed there. It would be more consistent
- to describe the register where the parm was passed,
- but in practice that register usually holds something else.
-
- If we use DECL_RTL, then we must use the declared type of
- the variable, not the type that it arrived in. */
+ /* Parm passed in registers and lives in registers or nowhere. */
+ code = DBX_REGPARM_STABS_CODE;
+ letter = DBX_REGPARM_STABS_LETTER;
+
+ /* For parms passed in registers, it is better to use the
+ declared type of the variable, not the type it arrived in. */
+ eff_type = TREE_TYPE (parms);
+
+ /* If parm lives in a register, use that register; pretend
+ the parm was passed there. It would be more consistent
+ to describe the register where the parm was passed, but
+ in practice that register usually holds something else.
+ If the parm lives nowhere, use the register where it
+ was passed. */
if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
- {
- best_rtl = DECL_RTL (parms);
- parm_type = TREE_TYPE (parms);
- }
- /* If the parm lives nowhere, use the register where it was
- passed. It is also better to use the declared type here. */
+ best_rtl = DECL_RTL (parms);
else
- {
- best_rtl = DECL_INCOMING_RTL (parms);
- parm_type = TREE_TYPE (parms);
- }
- current_sym_value = DBX_REGISTER_NUMBER (REGNO (best_rtl));
-
- FORCE_TEXT;
- if (DECL_NAME (parms))
- {
- current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));
- fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_NAME (parms)),
- regparm_letter);
- }
- else
- {
- current_sym_nchars = 8;
- fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP,
- regparm_letter);
- }
+ best_rtl = DECL_INCOMING_RTL (parms);
- dbxout_type (parm_type, 0);
- dbxout_finish_symbol (parms);
+ number = DBX_REGISTER_NUMBER (REGNO (best_rtl));
}
- else if (GET_CODE (DECL_RTL (parms)) == MEM
- && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
+ else if (MEM_P (DECL_RTL (parms))
+ && REG_P (XEXP (DECL_RTL (parms), 0))
&& REGNO (XEXP (DECL_RTL (parms), 0)) != HARD_FRAME_POINTER_REGNUM
&& REGNO (XEXP (DECL_RTL (parms), 0)) != STACK_POINTER_REGNUM
#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
@@ -2865,73 +3202,44 @@ dbxout_parms (tree parms)
The debugger will know from the type
that it was actually passed by invisible reference. */
- char regparm_letter;
- /* Parm passed in registers and lives in registers or nowhere. */
-
- current_sym_code = DBX_REGPARM_STABS_CODE;
- if (use_gnu_debug_info_extensions)
- regparm_letter = GDB_INV_REF_REGPARM_STABS_LETTER;
- else
- regparm_letter = DBX_REGPARM_STABS_LETTER;
+ code = DBX_REGPARM_STABS_CODE;
+
+ /* GDB likes this marked with a special letter. */
+ letter = (use_gnu_debug_info_extensions
+ ? 'a' : DBX_REGPARM_STABS_LETTER);
+ eff_type = TREE_TYPE (parms);
/* DECL_RTL looks like (MEM (REG...). Get the register number.
If it is an unallocated pseudo-reg, then use the register where
- it was passed instead. */
- if (REGNO (XEXP (DECL_RTL (parms), 0)) < FIRST_PSEUDO_REGISTER)
- current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0));
- else
- current_sym_value = REGNO (DECL_INCOMING_RTL (parms));
-
- current_sym_addr = 0;
-
- FORCE_TEXT;
- if (DECL_NAME (parms))
- {
- current_sym_nchars
- = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
+ it was passed instead.
+ ??? Why is DBX_REGISTER_NUMBER not used here? */
- fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_NAME (parms)),
- regparm_letter);
- }
+ if (REGNO (XEXP (DECL_RTL (parms), 0)) < FIRST_PSEUDO_REGISTER)
+ number = REGNO (XEXP (DECL_RTL (parms), 0));
else
- {
- current_sym_nchars = 8;
- fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP,
- regparm_letter);
- }
-
- dbxout_type (TREE_TYPE (parms), 0);
- dbxout_finish_symbol (parms);
+ number = REGNO (DECL_INCOMING_RTL (parms));
}
- else if (GET_CODE (DECL_RTL (parms)) == MEM
- && GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)
+ else if (MEM_P (DECL_RTL (parms))
+ && MEM_P (XEXP (DECL_RTL (parms), 0)))
{
/* Parm was passed via invisible reference, with the reference
living on the stack. DECL_RTL looks like
(MEM (MEM (PLUS (REG ...) (CONST_INT ...)))) or it
could look like (MEM (MEM (REG))). */
- const char *const decl_name = (DECL_NAME (parms)
- ? IDENTIFIER_POINTER (DECL_NAME (parms))
- : "(anon)");
- if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
- current_sym_value = 0;
+
+ code = N_PSYM;
+ letter = 'v';
+ eff_type = TREE_TYPE (parms);
+
+ if (!REG_P (XEXP (XEXP (DECL_RTL (parms), 0), 0)))
+ number = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1));
else
- current_sym_value
- = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1));
- current_sym_addr = 0;
- current_sym_code = N_PSYM;
-
- FORCE_TEXT;
- fprintf (asmfile, "%s\"%s:v", ASM_STABS_OP, decl_name);
-
- current_sym_value
- = DEBUGGER_ARG_OFFSET (current_sym_value,
- XEXP (XEXP (DECL_RTL (parms), 0), 0));
- dbxout_type (TREE_TYPE (parms), 0);
- dbxout_finish_symbol (parms);
+ number = 0;
+
+ number = DEBUGGER_ARG_OFFSET (number,
+ XEXP (XEXP (DECL_RTL (parms), 0), 0));
}
- else if (GET_CODE (DECL_RTL (parms)) == MEM
+ else if (MEM_P (DECL_RTL (parms))
&& XEXP (DECL_RTL (parms), 0) != const0_rtx
/* ??? A constant address for a parm can happen
when the reg it lives in is equiv to a constant in memory.
@@ -2940,53 +3248,43 @@ dbxout_parms (tree parms)
{
/* Parm was passed in registers but lives on the stack. */
- current_sym_code = N_PSYM;
+ code = N_PSYM;
+ letter = 'p';
+ eff_type = TREE_TYPE (parms);
+
/* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),
in which case we want the value of that CONST_INT,
or (MEM (REG ...)),
in which case we use a value of zero. */
- if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG)
- current_sym_value = 0;
+ if (!REG_P (XEXP (DECL_RTL (parms), 0)))
+ number = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
else
- current_sym_value
- = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
-
- current_sym_addr = 0;
+ number = 0;
/* Make a big endian correction if the mode of the type of the
parameter is not the same as the mode of the rtl. */
if (BYTES_BIG_ENDIAN
&& TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
&& GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
- {
- current_sym_value +=
- GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
- - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms)));
- }
-
- FORCE_TEXT;
- if (DECL_NAME (parms))
- {
- current_sym_nchars
- = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms)));
-
- fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_NAME (parms)),
- DBX_MEMPARM_STABS_LETTER);
- }
- else
- {
- current_sym_nchars = 8;
- fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP,
- DBX_MEMPARM_STABS_LETTER);
- }
+ number += (GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
+ - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))));
+ }
+ else
+ /* ??? We don't know how to represent this argument. */
+ continue;
- current_sym_value
- = DEBUGGER_ARG_OFFSET (current_sym_value,
- XEXP (DECL_RTL (parms), 0));
- dbxout_type (TREE_TYPE (parms), 0);
- dbxout_finish_symbol (parms);
+ dbxout_begin_complex_stabs ();
+
+ if (DECL_NAME (parms))
+ {
+ stabstr_I (DECL_NAME (parms));
+ stabstr_C (':');
}
+ else
+ stabstr_S ("(anon):");
+ stabstr_C (letter);
+ dbxout_type (eff_type, 0);
+ dbxout_finish_complex_stabs (parms, code, 0, 0, number);
}
DBXOUT_DECR_NESTING;
}
@@ -3010,11 +3308,9 @@ dbxout_reg_parms (tree parms)
for (; parms; parms = TREE_CHAIN (parms))
if (DECL_NAME (parms) && PARM_PASSED_IN_MEMORY (parms))
{
- dbxout_prepare_symbol (parms);
-
/* Report parms that live in registers during the function
but were passed in memory. */
- if (GET_CODE (DECL_RTL (parms)) == REG
+ if (REG_P (DECL_RTL (parms))
&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
dbxout_symbol_location (parms, TREE_TYPE (parms),
0, DECL_RTL (parms));
@@ -3022,7 +3318,7 @@ dbxout_reg_parms (tree parms)
dbxout_symbol_location (parms, TREE_TYPE (parms),
0, DECL_RTL (parms));
/* Report parms that live in memory but not where they were passed. */
- else if (GET_CODE (DECL_RTL (parms)) == MEM
+ else if (MEM_P (DECL_RTL (parms))
&& ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))
dbxout_symbol_location (parms, TREE_TYPE (parms),
0, DECL_RTL (parms));
@@ -3038,9 +3334,8 @@ dbxout_args (tree args)
{
while (args)
{
- putc (',', asmfile);
+ stabstr_C (',');
dbxout_type (TREE_VALUE (args), 0);
- CHARS (1);
args = TREE_CHAIN (args);
}
}
@@ -3052,17 +3347,11 @@ static void
dbx_output_lbrac (const char *label,
const char *begin_label ATTRIBUTE_UNUSED)
{
-#ifdef DBX_OUTPUT_LBRAC
- DBX_OUTPUT_LBRAC (asmfile, label);
-#else
- fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_LBRAC);
- assemble_name (asmfile, label);
-#if DBX_BLOCKS_FUNCTION_RELATIVE
- putc ('-', asmfile);
- assemble_name (asmfile, begin_label);
-#endif
- fprintf (asmfile, "\n");
-#endif
+ dbxout_begin_stabn (N_LBRAC);
+ if (DBX_BLOCKS_FUNCTION_RELATIVE)
+ dbxout_stab_value_label_diff (label, begin_label);
+ else
+ dbxout_stab_value_label (label);
}
/* Subroutine of dbxout_block. Emit an N_RBRAC stab referencing LABEL.
@@ -3072,17 +3361,11 @@ static void
dbx_output_rbrac (const char *label,
const char *begin_label ATTRIBUTE_UNUSED)
{
-#ifdef DBX_OUTPUT_RBRAC
- DBX_OUTPUT_RBRAC (asmfile, label);
-#else
- fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_RBRAC);
- assemble_name (asmfile, label);
-#if DBX_BLOCKS_FUNCTION_RELATIVE
- putc ('-', asmfile);
- assemble_name (asmfile, begin_label);
-#endif
- fprintf (asmfile, "\n");
-#endif
+ dbxout_begin_stabn (N_RBRAC);
+ if (DBX_BLOCKS_FUNCTION_RELATIVE)
+ dbxout_stab_value_label_diff (label, begin_label);
+ else
+ dbxout_stab_value_label (label);
}
/* Output everything about a symbol block (a BLOCK node
@@ -3105,11 +3388,9 @@ dbx_output_rbrac (const char *label,
static void
dbxout_block (tree block, int depth, tree args)
{
- const char *begin_label;
- if (current_function_func_begin_label != NULL_TREE)
- begin_label = IDENTIFIER_POINTER (current_function_func_begin_label);
- else
- begin_label = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ char begin_label[20];
+ /* Reference current function start using LFBB. */
+ ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
while (block)
{
@@ -3138,7 +3419,7 @@ dbxout_block (tree block, int depth, tree args)
if (depth == 0)
/* The outermost block doesn't get LBB labels; use
- the function symbol. */
+ the LFBB local symbol emitted by dbxout_begin_prologue. */
scope_start = begin_label;
else
{
@@ -3152,10 +3433,11 @@ dbxout_block (tree block, int depth, tree args)
tree decl = BLOCK_VARS (block);
while (decl)
{
- fprintf (asmfile, "%s\"%s:C1\",%d,0,0,", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_NAME (decl)), N_CATCH);
- assemble_name (asmfile, scope_start);
- fprintf (asmfile, "\n");
+ dbxout_begin_complex_stabs ();
+ stabstr_I (DECL_NAME (decl));
+ stabstr_S (":C1");
+ dbxout_finish_complex_stabs (0, N_CATCH, 0,
+ scope_start, 0);
decl = TREE_CHAIN (decl);
}
}
@@ -3192,7 +3474,12 @@ dbxout_block (tree block, int depth, tree args)
static void
dbxout_begin_function (tree decl)
{
- int saved_tree_used1 = TREE_USED (decl);
+ int saved_tree_used1;
+
+ if (DECL_IGNORED_P (decl))
+ return;
+
+ saved_tree_used1 = TREE_USED (decl);
TREE_USED (decl) = 1;
if (DECL_NAME (DECL_RESULT (decl)) != 0)
{
diff --git a/contrib/gcc/emit-rtl.c b/contrib/gcc/emit-rtl.c
index 9df2d6c..9607bf6 100644
--- a/contrib/gcc/emit-rtl.c
+++ b/contrib/gcc/emit-rtl.c
@@ -1,6 +1,7 @@
/* Emit RTL for the GCC expander.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,24 +17,22 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* Middle-to-low level generation of rtx code and insns.
- This file contains the functions `gen_rtx', `gen_reg_rtx'
- and `gen_label_rtx' that are the usual ways of creating rtl
- expressions for most purposes.
-
- It also has the functions for creating insns and linking
- them in the doubly-linked chain.
+ This file contains support functions for creating rtl expressions
+ and manipulating them in the doubly-linked chain of insns.
The patterns of the insns are created by machine-dependent
routines in insn-emit.c, which is generated automatically from
- the machine description. These routines use `gen_rtx' to make
- the individual rtx's of the pattern; what is machine dependent
- is the kind of rtx's they make and what arguments they use. */
+ the machine description. These routines make the individual rtx's
+ of the pattern with `gen_rtx_fmt_ee' and others in genrtl.[ch],
+ which are automatically generated from rtl.def; what is machine
+ dependent is the kind of rtx's they make and what arguments they
+ use. */
#include "config.h"
#include "system.h"
@@ -57,6 +56,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "debug.h"
#include "langhooks.h"
+#include "tree-pass.h"
/* Commonly used modes. */
@@ -71,17 +71,6 @@ enum machine_mode ptr_mode; /* Mode whose width is POINTER_SIZE. */
static GTY(()) int label_num = 1;
-/* Highest label number in current function.
- Zero means use the value of label_num instead.
- This is nonzero only when belatedly compiling an inline function. */
-
-static int last_label_num;
-
-/* Value label_num had when set_new_last_label_num was called.
- If label_num has not changed since then, last_label_num is valid. */
-
-static int base_label_num;
-
/* Nonzero means do not generate NOTEs for source line numbers. */
static int no_line_numbers;
@@ -176,7 +165,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
#define last_location (cfun->emit->x_last_location)
#define first_label_num (cfun->emit->x_first_label_num)
-static rtx make_jump_insn_raw (rtx);
static rtx make_call_insn_raw (rtx);
static rtx find_line_note (rtx);
static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
@@ -196,8 +184,7 @@ static hashval_t reg_attrs_htab_hash (const void *);
static int reg_attrs_htab_eq (const void *, const void *);
static reg_attrs *get_reg_attrs (tree, int);
static tree component_ref_for_mem_expr (tree);
-static rtx gen_const_vector_0 (enum machine_mode);
-static rtx gen_complex_constant_part (enum machine_mode, rtx, int);
+static rtx gen_const_vector (enum machine_mode, int);
static void copy_rtx_if_shared_1 (rtx *orig);
/* Probability of the conditional branch currently proceeded by try_split.
@@ -267,7 +254,7 @@ mem_attrs_htab_hash (const void *x)
return (p->alias ^ (p->align * 1000)
^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
- ^ (size_t) p->expr);
+ ^ (size_t) iterative_hash_expr (p->expr, 0));
}
/* Returns nonzero if the value represented by X (which is really a
@@ -280,8 +267,11 @@ mem_attrs_htab_eq (const void *x, const void *y)
mem_attrs *p = (mem_attrs *) x;
mem_attrs *q = (mem_attrs *) y;
- return (p->alias == q->alias && p->expr == q->expr && p->offset == q->offset
- && p->size == q->size && p->align == q->align);
+ return (p->alias == q->alias && p->offset == q->offset
+ && p->size == q->size && p->align == q->align
+ && (p->expr == q->expr
+ || (p->expr != NULL_TREE && q->expr != NULL_TREE
+ && operand_equal_p (p->expr, q->expr, 0))));
}
/* Allocate a new mem_attrs structure and insert it into the hash table if
@@ -439,7 +429,7 @@ const_double_from_real_value (REAL_VALUE_TYPE value, enum machine_mode mode)
rtx real = rtx_alloc (CONST_DOUBLE);
PUT_MODE (real, mode);
- memcpy (&CONST_DOUBLE_LOW (real), &value, sizeof (REAL_VALUE_TYPE));
+ real->u.rv = value;
return lookup_const_double (real);
}
@@ -455,64 +445,28 @@ immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, enum machine_mode mode)
rtx value;
unsigned int i;
+ /* There are the following cases (note that there are no modes with
+ HOST_BITS_PER_WIDE_INT < GET_MODE_BITSIZE (mode) < 2 * HOST_BITS_PER_WIDE_INT):
+
+ 1) If GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT, then we use
+ gen_int_mode.
+ 2) GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT, but the value of
+ the integer fits into HOST_WIDE_INT anyway (i.e., i1 consists only
+ from copies of the sign bit, and sign of i0 and i1 are the same), then
+ we return a CONST_INT for i0.
+ 3) Otherwise, we create a CONST_DOUBLE for i0 and i1. */
if (mode != VOIDmode)
{
- int width;
- if (GET_MODE_CLASS (mode) != MODE_INT
- && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT
- /* We can get a 0 for an error mark. */
- && GET_MODE_CLASS (mode) != MODE_VECTOR_INT
- && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT)
- abort ();
-
- /* We clear out all bits that don't belong in MODE, unless they and
- our sign bit are all one. So we get either a reasonable negative
- value or a reasonable unsigned value for this mode. */
- width = GET_MODE_BITSIZE (mode);
- if (width < HOST_BITS_PER_WIDE_INT
- && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1)))
- != ((HOST_WIDE_INT) (-1) << (width - 1))))
- i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0;
- else if (width == HOST_BITS_PER_WIDE_INT
- && ! (i1 == ~0 && i0 < 0))
- i1 = 0;
- else if (width > 2 * HOST_BITS_PER_WIDE_INT)
- /* We cannot represent this value as a constant. */
- abort ();
-
- /* If this would be an entire word for the target, but is not for
- the host, then sign-extend on the host so that the number will
- look the same way on the host that it would on the target.
-
- For example, when building a 64 bit alpha hosted 32 bit sparc
- targeted compiler, then we want the 32 bit unsigned value -1 to be
- represented as a 64 bit value -1, and not as 0x00000000ffffffff.
- The latter confuses the sparc backend. */
-
- if (width < HOST_BITS_PER_WIDE_INT
- && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
- i0 |= ((HOST_WIDE_INT) (-1) << width);
-
- /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a
- CONST_INT.
-
- ??? Strictly speaking, this is wrong if we create a CONST_INT for
- a large unsigned constant with the size of MODE being
- HOST_BITS_PER_WIDE_INT and later try to interpret that constant
- in a wider mode. In that case we will mis-interpret it as a
- negative number.
-
- Unfortunately, the only alternative is to make a CONST_DOUBLE for
- any constant in any mode if it is an unsigned constant larger
- than the maximum signed integer in an int on the host. However,
- doing this will break everyone that always expects to see a
- CONST_INT for SImode and smaller.
-
- We have always been making CONST_INTs in this case, so nothing
- new is being broken. */
-
- if (width <= HOST_BITS_PER_WIDE_INT)
- i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0;
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
+ || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
+ /* We can get a 0 for an error mark. */
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
+
+ if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+ return gen_int_mode (i0, mode);
+
+ gcc_assert (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT);
}
/* If this integer fits in one word, return a CONST_INT. */
@@ -609,153 +563,152 @@ gen_rtx_MEM (enum machine_mode mode, rtx addr)
return rt;
}
+/* Generate a memory referring to non-trapping constant memory. */
+
rtx
-gen_rtx_SUBREG (enum machine_mode mode, rtx reg, int offset)
+gen_const_mem (enum machine_mode mode, rtx addr)
{
- /* This is the most common failure type.
- Catch it early so we can see who does it. */
- if ((offset % GET_MODE_SIZE (mode)) != 0)
- abort ();
-
- /* This check isn't usable right now because combine will
- throw arbitrary crap like a CALL into a SUBREG in
- gen_lowpart_for_combine so we must just eat it. */
-#if 0
- /* Check for this too. */
- if (offset >= GET_MODE_SIZE (GET_MODE (reg)))
- abort ();
-#endif
- return gen_rtx_raw_SUBREG (mode, reg, offset);
+ rtx mem = gen_rtx_MEM (mode, addr);
+ MEM_READONLY_P (mem) = 1;
+ MEM_NOTRAP_P (mem) = 1;
+ return mem;
}
-/* Generate a SUBREG representing the least-significant part of REG if MODE
- is smaller than mode of REG, otherwise paradoxical SUBREG. */
+/* Generate a MEM referring to fixed portions of the frame, e.g., register
+ save areas. */
rtx
-gen_lowpart_SUBREG (enum machine_mode mode, rtx reg)
+gen_frame_mem (enum machine_mode mode, rtx addr)
{
- enum machine_mode inmode;
-
- inmode = GET_MODE (reg);
- if (inmode == VOIDmode)
- inmode = mode;
- return gen_rtx_SUBREG (mode, reg,
- subreg_lowpart_offset (mode, inmode));
+ rtx mem = gen_rtx_MEM (mode, addr);
+ MEM_NOTRAP_P (mem) = 1;
+ set_mem_alias_set (mem, get_frame_alias_set ());
+ return mem;
}
-
-/* rtx gen_rtx (code, mode, [element1, ..., elementn])
-**
-** This routine generates an RTX of the size specified by
-** <code>, which is an RTX code. The RTX structure is initialized
-** from the arguments <element1> through <elementn>, which are
-** interpreted according to the specific RTX type's format. The
-** special machine mode associated with the rtx (if any) is specified
-** in <mode>.
-**
-** gen_rtx can be invoked in a way which resembles the lisp-like
-** rtx it will generate. For example, the following rtx structure:
-**
-** (plus:QI (mem:QI (reg:SI 1))
-** (mem:QI (plusw:SI (reg:SI 2) (reg:SI 3))))
-**
-** ...would be generated by the following C code:
-**
-** gen_rtx (PLUS, QImode,
-** gen_rtx (MEM, QImode,
-** gen_rtx (REG, SImode, 1)),
-** gen_rtx (MEM, QImode,
-** gen_rtx (PLUS, SImode,
-** gen_rtx (REG, SImode, 2),
-** gen_rtx (REG, SImode, 3)))),
-*/
-/*VARARGS2*/
+/* Generate a MEM referring to a temporary use of the stack, not part
+ of the fixed stack frame. For example, something which is pushed
+ by a target splitter. */
rtx
-gen_rtx (enum rtx_code code, enum machine_mode mode, ...)
+gen_tmp_stack_mem (enum machine_mode mode, rtx addr)
{
- int i; /* Array indices... */
- const char *fmt; /* Current rtx's format... */
- rtx rt_val; /* RTX to return to caller... */
- va_list p;
-
- va_start (p, mode);
-
- switch (code)
- {
- case CONST_INT:
- rt_val = gen_rtx_CONST_INT (mode, va_arg (p, HOST_WIDE_INT));
- break;
+ rtx mem = gen_rtx_MEM (mode, addr);
+ MEM_NOTRAP_P (mem) = 1;
+ if (!current_function_calls_alloca)
+ set_mem_alias_set (mem, get_frame_alias_set ());
+ return mem;
+}
- case CONST_DOUBLE:
- {
- HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
- HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
+/* We want to create (subreg:OMODE (obj:IMODE) OFFSET). Return true if
+ this construct would be valid, and false otherwise. */
- rt_val = immed_double_const (arg0, arg1, mode);
- }
- break;
+bool
+validate_subreg (enum machine_mode omode, enum machine_mode imode,
+ rtx reg, unsigned int offset)
+{
+ unsigned int isize = GET_MODE_SIZE (imode);
+ unsigned int osize = GET_MODE_SIZE (omode);
- case REG:
- rt_val = gen_rtx_REG (mode, va_arg (p, int));
- break;
+ /* All subregs must be aligned. */
+ if (offset % osize != 0)
+ return false;
- case MEM:
- rt_val = gen_rtx_MEM (mode, va_arg (p, rtx));
- break;
+ /* The subreg offset cannot be outside the inner object. */
+ if (offset >= isize)
+ return false;
- default:
- rt_val = rtx_alloc (code); /* Allocate the storage space. */
- rt_val->mode = mode; /* Store the machine mode... */
+ /* ??? This should not be here. Temporarily continue to allow word_mode
+ subregs of anything. The most common offender is (subreg:SI (reg:DF)).
+ Generally, backends are doing something sketchy but it'll take time to
+ fix them all. */
+ if (omode == word_mode)
+ ;
+ /* ??? Similarly, e.g. with (subreg:DF (reg:TI)). Though store_bit_field
+ is the culprit here, and not the backends. */
+ else if (osize >= UNITS_PER_WORD && isize >= osize)
+ ;
+ /* Allow component subregs of complex and vector. Though given the below
+ extraction rules, it's not always clear what that means. */
+ else if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode))
+ && GET_MODE_INNER (imode) == omode)
+ ;
+ /* ??? x86 sse code makes heavy use of *paradoxical* vector subregs,
+ i.e. (subreg:V4SF (reg:SF) 0). This surely isn't the cleanest way to
+ represent this. It's questionable if this ought to be represented at
+ all -- why can't this all be hidden in post-reload splitters that make
+ arbitrarily mode changes to the registers themselves. */
+ else if (VECTOR_MODE_P (omode) && GET_MODE_INNER (omode) == imode)
+ ;
+ /* Subregs involving floating point modes are not allowed to
+ change size. Therefore (subreg:DI (reg:DF) 0) is fine, but
+ (subreg:SI (reg:DF) 0) isn't. */
+ else if (FLOAT_MODE_P (imode) || FLOAT_MODE_P (omode))
+ {
+ if (isize != osize)
+ return false;
+ }
- fmt = GET_RTX_FORMAT (code); /* Find the right format... */
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- {
- switch (*fmt++)
- {
- case '0': /* Field with unknown use. Zero it. */
- X0EXP (rt_val, i) = NULL_RTX;
- break;
+ /* Paradoxical subregs must have offset zero. */
+ if (osize > isize)
+ return offset == 0;
- case 'i': /* An integer? */
- XINT (rt_val, i) = va_arg (p, int);
- break;
+ /* This is a normal subreg. Verify that the offset is representable. */
- case 'w': /* A wide integer? */
- XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT);
- break;
+ /* For hard registers, we already have most of these rules collected in
+ subreg_offset_representable_p. */
+ if (reg && REG_P (reg) && HARD_REGISTER_P (reg))
+ {
+ unsigned int regno = REGNO (reg);
- case 's': /* A string? */
- XSTR (rt_val, i) = va_arg (p, char *);
- break;
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode))
+ && GET_MODE_INNER (imode) == omode)
+ ;
+ else if (REG_CANNOT_CHANGE_MODE_P (regno, imode, omode))
+ return false;
+#endif
- case 'e': /* An expression? */
- case 'u': /* An insn? Same except when printing. */
- XEXP (rt_val, i) = va_arg (p, rtx);
- break;
+ return subreg_offset_representable_p (regno, imode, offset, omode);
+ }
- case 'E': /* An RTX vector? */
- XVEC (rt_val, i) = va_arg (p, rtvec);
- break;
+ /* For pseudo registers, we want most of the same checks. Namely:
+ If the register no larger than a word, the subreg must be lowpart.
+ If the register is larger than a word, the subreg must be the lowpart
+ of a subword. A subreg does *not* perform arbitrary bit extraction.
+ Given that we've already checked mode/offset alignment, we only have
+ to check subword subregs here. */
+ if (osize < UNITS_PER_WORD)
+ {
+ enum machine_mode wmode = isize > UNITS_PER_WORD ? word_mode : imode;
+ unsigned int low_off = subreg_lowpart_offset (omode, wmode);
+ if (offset % UNITS_PER_WORD != low_off)
+ return false;
+ }
+ return true;
+}
- case 'b': /* A bitmap? */
- XBITMAP (rt_val, i) = va_arg (p, bitmap);
- break;
+rtx
+gen_rtx_SUBREG (enum machine_mode mode, rtx reg, int offset)
+{
+ gcc_assert (validate_subreg (mode, GET_MODE (reg), reg, offset));
+ return gen_rtx_raw_SUBREG (mode, reg, offset);
+}
- case 't': /* A tree? */
- XTREE (rt_val, i) = va_arg (p, tree);
- break;
+/* Generate a SUBREG representing the least-significant part of REG if MODE
+ is smaller than mode of REG, otherwise paradoxical SUBREG. */
- default:
- abort ();
- }
- }
- break;
- }
+rtx
+gen_lowpart_SUBREG (enum machine_mode mode, rtx reg)
+{
+ enum machine_mode inmode;
- va_end (p);
- return rt_val;
+ inmode = GET_MODE (reg);
+ if (inmode == VOIDmode)
+ inmode = mode;
+ return gen_rtx_SUBREG (mode, reg,
+ subreg_lowpart_offset (mode, inmode));
}
-
+
/* gen_rtvec (n, [rt1, ..., rtn])
**
** This routine creates an rtvec and stores within it the
@@ -815,8 +768,7 @@ gen_reg_rtx (enum machine_mode mode)
/* Don't let anything called after initial flow analysis create new
registers. */
- if (no_new_pseudos)
- abort ();
+ gcc_assert (!no_new_pseudos);
if (generating_concat_p
&& (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
@@ -861,13 +813,96 @@ gen_reg_rtx (enum machine_mode mode)
return val;
}
-/* Generate a register with same attributes as REG,
- but offsetted by OFFSET. */
+/* Generate a register with same attributes as REG, but offsetted by OFFSET.
+ Do the big endian correction if needed. */
rtx
gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int offset)
{
rtx new = gen_rtx_REG (mode, regno);
+ tree decl;
+ HOST_WIDE_INT var_size;
+
+ /* PR middle-end/14084
+ The problem appears when a variable is stored in a larger register
+ and later it is used in the original mode or some mode in between
+ or some part of variable is accessed.
+
+ On little endian machines there is no problem because
+ the REG_OFFSET of the start of the variable is the same when
+ accessed in any mode (it is 0).
+
+ However, this is not true on big endian machines.
+ The offset of the start of the variable is different when accessed
+ in different modes.
+ When we are taking a part of the REG we have to change the OFFSET
+ from offset WRT size of mode of REG to offset WRT size of variable.
+
+ If we would not do the big endian correction the resulting REG_OFFSET
+ would be larger than the size of the DECL.
+
+ Examples of correction, for BYTES_BIG_ENDIAN WORDS_BIG_ENDIAN machine:
+
+ REG.mode MODE DECL size old offset new offset description
+ DI SI 4 4 0 int32 in SImode
+ DI SI 1 4 0 char in SImode
+ DI QI 1 7 0 char in QImode
+ DI QI 4 5 1 1st element in QImode
+ of char[4]
+ DI HI 4 6 2 1st element in HImode
+ of int16[2]
+
+ If the size of DECL is equal or greater than the size of REG
+ we can't do this correction because the register holds the
+ whole variable or a part of the variable and thus the REG_OFFSET
+ is already correct. */
+
+ decl = REG_EXPR (reg);
+ if ((BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
+ && decl != NULL
+ && offset > 0
+ && GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode)
+ && ((var_size = int_size_in_bytes (TREE_TYPE (decl))) > 0
+ && var_size < GET_MODE_SIZE (GET_MODE (reg))))
+ {
+ int offset_le;
+
+ /* Convert machine endian to little endian WRT size of mode of REG. */
+ if (WORDS_BIG_ENDIAN)
+ offset_le = ((GET_MODE_SIZE (GET_MODE (reg)) - 1 - offset)
+ / UNITS_PER_WORD) * UNITS_PER_WORD;
+ else
+ offset_le = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
+
+ if (BYTES_BIG_ENDIAN)
+ offset_le += ((GET_MODE_SIZE (GET_MODE (reg)) - 1 - offset)
+ % UNITS_PER_WORD);
+ else
+ offset_le += offset % UNITS_PER_WORD;
+
+ if (offset_le >= var_size)
+ {
+ /* MODE is wider than the variable so the new reg will cover
+ the whole variable so the resulting OFFSET should be 0. */
+ offset = 0;
+ }
+ else
+ {
+ /* Convert little endian to machine endian WRT size of variable. */
+ if (WORDS_BIG_ENDIAN)
+ offset = ((var_size - 1 - offset_le)
+ / UNITS_PER_WORD) * UNITS_PER_WORD;
+ else
+ offset = (offset_le / UNITS_PER_WORD) * UNITS_PER_WORD;
+
+ if (BYTES_BIG_ENDIAN)
+ offset += ((var_size - 1 - offset_le)
+ % UNITS_PER_WORD);
+ else
+ offset += offset_le % UNITS_PER_WORD;
+ }
+ }
+
REG_ATTRS (new) = get_reg_attrs (REG_EXPR (reg),
REG_OFFSET (reg) + offset);
return new;
@@ -889,7 +924,7 @@ set_reg_attrs_from_mem (rtx reg, rtx mem)
void
set_reg_attrs_for_parm (rtx parm_rtx, rtx mem)
{
- if (GET_CODE (parm_rtx) == REG)
+ if (REG_P (parm_rtx))
set_reg_attrs_from_mem (parm_rtx, mem);
else if (GET_CODE (parm_rtx) == PARALLEL)
{
@@ -899,7 +934,7 @@ set_reg_attrs_for_parm (rtx parm_rtx, rtx mem)
for (; i < XVECLEN (parm_rtx, 0); i++)
{
rtx x = XVECEXP (parm_rtx, 0, i);
- if (GET_CODE (XEXP (x, 0)) == REG)
+ if (REG_P (XEXP (x, 0)))
REG_ATTRS (XEXP (x, 0))
= get_reg_attrs (MEM_EXPR (mem),
INTVAL (XEXP (x, 1)));
@@ -911,12 +946,12 @@ set_reg_attrs_for_parm (rtx parm_rtx, rtx mem)
void
set_decl_rtl (tree t, rtx x)
{
- DECL_CHECK (t)->decl.rtl = x;
+ DECL_WRTL_CHECK (t)->decl_with_rtl.rtl = x;
if (!x)
return;
/* For register, we maintain the reverse information too. */
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
REG_ATTRS (x) = get_reg_attrs (t, 0);
else if (GET_CODE (x) == SUBREG)
REG_ATTRS (SUBREG_REG (x))
@@ -941,6 +976,48 @@ set_decl_rtl (tree t, rtx x)
}
}
+/* Assign the RTX X to parameter declaration T. */
+void
+set_decl_incoming_rtl (tree t, rtx x)
+{
+ DECL_INCOMING_RTL (t) = x;
+
+ if (!x)
+ return;
+ /* For register, we maintain the reverse information too. */
+ if (REG_P (x))
+ REG_ATTRS (x) = get_reg_attrs (t, 0);
+ else if (GET_CODE (x) == SUBREG)
+ REG_ATTRS (SUBREG_REG (x))
+ = get_reg_attrs (t, -SUBREG_BYTE (x));
+ if (GET_CODE (x) == CONCAT)
+ {
+ if (REG_P (XEXP (x, 0)))
+ REG_ATTRS (XEXP (x, 0)) = get_reg_attrs (t, 0);
+ if (REG_P (XEXP (x, 1)))
+ REG_ATTRS (XEXP (x, 1))
+ = get_reg_attrs (t, GET_MODE_UNIT_SIZE (GET_MODE (XEXP (x, 0))));
+ }
+ if (GET_CODE (x) == PARALLEL)
+ {
+ int i, start;
+
+ /* Check for a NULL entry, used to indicate that the parameter goes
+ both on the stack and in registers. */
+ if (XEXP (XVECEXP (x, 0, 0), 0))
+ start = 0;
+ else
+ start = 1;
+
+ for (i = start; i < XVECLEN (x, 0); i++)
+ {
+ rtx y = XVECEXP (x, 0, i);
+ if (REG_P (XEXP (y, 0)))
+ REG_ATTRS (XEXP (y, 0)) = get_reg_attrs (t, INTVAL (XEXP (y, 1)));
+ }
+ }
+}
+
/* Identify REG (which may be a CONCAT) as a user register. */
void
@@ -951,10 +1028,11 @@ mark_user_reg (rtx reg)
REG_USERVAR_P (XEXP (reg, 0)) = 1;
REG_USERVAR_P (XEXP (reg, 1)) = 1;
}
- else if (GET_CODE (reg) == REG)
- REG_USERVAR_P (reg) = 1;
else
- abort ();
+ {
+ gcc_assert (REG_P (reg));
+ REG_USERVAR_P (reg) = 1;
+ }
}
/* Identify REG as a probable pointer register and show its alignment
@@ -988,8 +1066,6 @@ max_reg_num (void)
int
max_label_num (void)
{
- if (last_label_num && label_num == base_label_num)
- return last_label_num;
return label_num;
}
@@ -1000,41 +1076,18 @@ get_first_label_num (void)
{
return first_label_num;
}
-
-/* Return the final regno of X, which is a SUBREG of a hard
- register. */
-int
-subreg_hard_regno (rtx x, int check_mode)
-{
- enum machine_mode mode = GET_MODE (x);
- unsigned int byte_offset, base_regno, final_regno;
- rtx reg = SUBREG_REG (x);
-
- /* This is where we attempt to catch illegal subregs
- created by the compiler. */
- if (GET_CODE (x) != SUBREG
- || GET_CODE (reg) != REG)
- abort ();
- base_regno = REGNO (reg);
- if (base_regno >= FIRST_PSEUDO_REGISTER)
- abort ();
- if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
- abort ();
-#ifdef ENABLE_CHECKING
- if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg),
- SUBREG_BYTE (x), mode))
- abort ();
-#endif
- /* Catch non-congruent offsets too. */
- byte_offset = SUBREG_BYTE (x);
- if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
- abort ();
- final_regno = subreg_regno (x);
+/* If the rtx for label was created during the expansion of a nested
+ function, then first_label_num won't include this label number.
+ Fix this now so that array indicies work later. */
- return final_regno;
+void
+maybe_set_first_label_num (rtx x)
+{
+ if (CODE_LABEL_NUMBER (x) < first_label_num)
+ first_label_num = CODE_LABEL_NUMBER (x);
}
-
+
/* Return a value representing some low-order bits of X, where the number
of low-order bits is given by MODE. Note that no conversion is done
between floating-point and fixed-point values, rather, the bit
@@ -1057,15 +1110,15 @@ gen_lowpart_common (enum machine_mode mode, rtx x)
/* Unfortunately, this routine doesn't take a parameter for the mode of X,
so we have to make one up. Yuk. */
innermode = GET_MODE (x);
- if (GET_CODE (x) == CONST_INT && msize <= HOST_BITS_PER_WIDE_INT)
+ if (GET_CODE (x) == CONST_INT
+ && msize * BITS_PER_UNIT <= HOST_BITS_PER_WIDE_INT)
innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
else if (innermode == VOIDmode)
innermode = mode_for_size (HOST_BITS_PER_WIDE_INT * 2, MODE_INT, 0);
xsize = GET_MODE_SIZE (innermode);
- if (innermode == VOIDmode || innermode == BLKmode)
- abort ();
+ gcc_assert (innermode != VOIDmode && innermode != BLKmode);
if (innermode == mode)
return x;
@@ -1076,7 +1129,7 @@ gen_lowpart_common (enum machine_mode mode, rtx x)
return 0;
/* Don't allow generating paradoxical FLOAT_MODE subregs. */
- if (GET_MODE_CLASS (mode) == MODE_FLOAT && msize > xsize)
+ if (SCALAR_FLOAT_MODE_P (mode) && msize > xsize)
return 0;
offset = subreg_lowpart_offset (mode, innermode);
@@ -1100,7 +1153,7 @@ gen_lowpart_common (enum machine_mode mode, rtx x)
else if (msize < xsize)
return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
}
- else if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG
+ else if (GET_CODE (x) == SUBREG || REG_P (x)
|| GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR
|| GET_CODE (x) == CONST_DOUBLE || GET_CODE (x) == CONST_INT)
return simplify_gen_subreg (mode, x, innermode, offset);
@@ -1109,152 +1162,6 @@ gen_lowpart_common (enum machine_mode mode, rtx x)
return 0;
}
-/* Return the constant real or imaginary part (which has mode MODE)
- of a complex value X. The IMAGPART_P argument determines whether
- the real or complex component should be returned. This function
- returns NULL_RTX if the component isn't a constant. */
-
-static rtx
-gen_complex_constant_part (enum machine_mode mode, rtx x, int imagpart_p)
-{
- tree decl, part;
-
- if (GET_CODE (x) == MEM
- && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
- {
- decl = SYMBOL_REF_DECL (XEXP (x, 0));
- if (decl != NULL_TREE && TREE_CODE (decl) == COMPLEX_CST)
- {
- part = imagpart_p ? TREE_IMAGPART (decl) : TREE_REALPART (decl);
- if (TREE_CODE (part) == REAL_CST
- || TREE_CODE (part) == INTEGER_CST)
- return expand_expr (part, NULL_RTX, mode, 0);
- }
- }
- return NULL_RTX;
-}
-
-/* Return the real part (which has mode MODE) of a complex value X.
- This always comes at the low address in memory. */
-
-rtx
-gen_realpart (enum machine_mode mode, rtx x)
-{
- rtx part;
-
- /* Handle complex constants. */
- part = gen_complex_constant_part (mode, x, 0);
- if (part != NULL_RTX)
- return part;
-
- if (WORDS_BIG_ENDIAN
- && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
- && REG_P (x)
- && REGNO (x) < FIRST_PSEUDO_REGISTER)
- internal_error
- ("can't access real part of complex value in hard register");
- else if (WORDS_BIG_ENDIAN)
- return gen_highpart (mode, x);
- else
- return gen_lowpart (mode, x);
-}
-
-/* Return the imaginary part (which has mode MODE) of a complex value X.
- This always comes at the high address in memory. */
-
-rtx
-gen_imagpart (enum machine_mode mode, rtx x)
-{
- rtx part;
-
- /* Handle complex constants. */
- part = gen_complex_constant_part (mode, x, 1);
- if (part != NULL_RTX)
- return part;
-
- if (WORDS_BIG_ENDIAN)
- return gen_lowpart (mode, x);
- else if (! WORDS_BIG_ENDIAN
- && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
- && REG_P (x)
- && REGNO (x) < FIRST_PSEUDO_REGISTER)
- internal_error
- ("can't access imaginary part of complex value in hard register");
- else
- return gen_highpart (mode, x);
-}
-
-/* Return 1 iff X, assumed to be a SUBREG,
- refers to the real part of the complex value in its containing reg.
- Complex values are always stored with the real part in the first word,
- regardless of WORDS_BIG_ENDIAN. */
-
-int
-subreg_realpart_p (rtx x)
-{
- if (GET_CODE (x) != SUBREG)
- abort ();
-
- return ((unsigned int) SUBREG_BYTE (x)
- < (unsigned int) GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))));
-}
-
-/* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a value,
- return an rtx (MEM, SUBREG, or CONST_INT) that refers to the
- least-significant part of X.
- MODE specifies how big a part of X to return;
- it usually should not be larger than a word.
- If X is a MEM whose address is a QUEUED, the value may be so also. */
-
-rtx
-gen_lowpart (enum machine_mode mode, rtx x)
-{
- rtx result = gen_lowpart_common (mode, x);
-
- if (result)
- return result;
- else if (GET_CODE (x) == REG)
- {
- /* Must be a hard reg that's not valid in MODE. */
- result = gen_lowpart_common (mode, copy_to_reg (x));
- if (result == 0)
- abort ();
- return result;
- }
- else if (GET_CODE (x) == MEM)
- {
- /* The only additional case we can do is MEM. */
- int offset = 0;
-
- /* The following exposes the use of "x" to CSE. */
- if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
- && SCALAR_INT_MODE_P (GET_MODE (x))
- && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
- GET_MODE_BITSIZE (GET_MODE (x)))
- && ! no_new_pseudos)
- return gen_lowpart (mode, force_reg (GET_MODE (x), x));
-
- if (WORDS_BIG_ENDIAN)
- offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
-
- if (BYTES_BIG_ENDIAN)
- /* Adjust the address so that the address-after-the-data
- is unchanged. */
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
-
- return adjust_address (x, mode, offset);
- }
- else if (GET_CODE (x) == ADDRESSOF)
- return gen_lowpart (mode, force_reg (GET_MODE (x), x));
- else
- abort ();
-}
-
-/* Like `gen_lowpart', but refer to the most significant part.
- This is used to access the imaginary part of a complex number. */
-
rtx
gen_highpart (enum machine_mode mode, rtx x)
{
@@ -1263,21 +1170,22 @@ gen_highpart (enum machine_mode mode, rtx x)
/* This case loses if X is a subreg. To catch bugs early,
complain if an invalid MODE is used even in other cases. */
- if (msize > UNITS_PER_WORD
- && msize != (unsigned int) GET_MODE_UNIT_SIZE (GET_MODE (x)))
- abort ();
+ gcc_assert (msize <= UNITS_PER_WORD
+ || msize == (unsigned int) GET_MODE_UNIT_SIZE (GET_MODE (x)));
result = simplify_gen_subreg (mode, x, GET_MODE (x),
subreg_highpart_offset (mode, GET_MODE (x)));
-
+ gcc_assert (result);
+
/* simplify_gen_subreg is not guaranteed to return a valid operand for
the target if we have a MEM. gen_highpart must return a valid operand,
emitting code if necessary to do so. */
- if (result != NULL_RTX && GET_CODE (result) == MEM)
- result = validize_mem (result);
-
- if (!result)
- abort ();
+ if (MEM_P (result))
+ {
+ result = validize_mem (result);
+ gcc_assert (result);
+ }
+
return result;
}
@@ -1288,8 +1196,7 @@ gen_highpart_mode (enum machine_mode outermode, enum machine_mode innermode, rtx
{
if (GET_MODE (exp) != VOIDmode)
{
- if (GET_MODE (exp) != innermode)
- abort ();
+ gcc_assert (GET_MODE (exp) == innermode);
return gen_highpart (outermode, exp);
}
return simplify_gen_subreg (outermode, exp, innermode,
@@ -1324,8 +1231,7 @@ subreg_highpart_offset (enum machine_mode outermode, enum machine_mode innermode
unsigned int offset = 0;
int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
- if (GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode))
- abort ();
+ gcc_assert (GET_MODE_SIZE (innermode) >= GET_MODE_SIZE (outermode));
if (difference > 0)
{
@@ -1385,8 +1291,7 @@ operand_subword (rtx op, unsigned int offset, int validate_address, enum machine
if (mode == VOIDmode)
mode = GET_MODE (op);
- if (mode == VOIDmode)
- abort ();
+ gcc_assert (mode != VOIDmode);
/* If OP is narrower than a word, fail. */
if (mode != BLKmode
@@ -1399,7 +1304,7 @@ operand_subword (rtx op, unsigned int offset, int validate_address, enum machine
return const0_rtx;
/* Form a new MEM at the requested address. */
- if (GET_CODE (op) == MEM)
+ if (MEM_P (op))
{
rtx new = adjust_address_nv (op, word_mode, offset * UNITS_PER_WORD);
@@ -1419,9 +1324,10 @@ operand_subword (rtx op, unsigned int offset, int validate_address, enum machine
return simplify_gen_subreg (word_mode, op, mode, (offset * UNITS_PER_WORD));
}
-/* Similar to `operand_subword', but never return 0. If we can't extract
- the required subword, put OP into a register and try again. If that fails,
- abort. We always validate the address in this case.
+/* Similar to `operand_subword', but never return 0. If we can't
+ extract the required subword, put OP into a register and try again.
+ The second attempt must succeed. We always validate the address in
+ this case.
MODE is the mode of OP, in case it is CONST_INT. */
@@ -1437,51 +1343,18 @@ operand_subword_force (rtx op, unsigned int offset, enum machine_mode mode)
{
/* If this is a register which can not be accessed by words, copy it
to a pseudo register. */
- if (GET_CODE (op) == REG)
+ if (REG_P (op))
op = copy_to_reg (op);
else
op = force_reg (mode, op);
}
result = operand_subword (op, offset, 1, mode);
- if (result == 0)
- abort ();
+ gcc_assert (result);
return result;
}
-/* Given a compare instruction, swap the operands.
- A test instruction is changed into a compare of 0 against the operand. */
-
-void
-reverse_comparison (rtx insn)
-{
- rtx body = PATTERN (insn);
- rtx comp;
-
- if (GET_CODE (body) == SET)
- comp = SET_SRC (body);
- else
- comp = SET_SRC (XVECEXP (body, 0, 0));
-
- if (GET_CODE (comp) == COMPARE)
- {
- rtx op0 = XEXP (comp, 0);
- rtx op1 = XEXP (comp, 1);
- XEXP (comp, 0) = op1;
- XEXP (comp, 1) = op0;
- }
- else
- {
- rtx new = gen_rtx_COMPARE (VOIDmode,
- CONST0_RTX (GET_MODE (comp)), comp);
- if (GET_CODE (body) == SET)
- SET_SRC (body) = new;
- else
- SET_SRC (XVECEXP (body, 0, 0)) = new;
- }
-}
-
/* Within a MEM_EXPR, we care about either (1) a component ref of a decl,
or (2) a component ref of something variable. Represent the later with
a NULL expression. */
@@ -1495,19 +1368,13 @@ component_ref_for_mem_expr (tree ref)
inner = component_ref_for_mem_expr (inner);
else
{
- tree placeholder_ptr = 0;
-
/* Now remove any conversions: they don't change what the underlying
- object is. Likewise for SAVE_EXPR. Also handle PLACEHOLDER_EXPR. */
+ object is. Likewise for SAVE_EXPR. */
while (TREE_CODE (inner) == NOP_EXPR || TREE_CODE (inner) == CONVERT_EXPR
|| TREE_CODE (inner) == NON_LVALUE_EXPR
|| TREE_CODE (inner) == VIEW_CONVERT_EXPR
- || TREE_CODE (inner) == SAVE_EXPR
- || TREE_CODE (inner) == PLACEHOLDER_EXPR)
- if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
- inner = find_placeholder (inner, &placeholder_ptr);
- else
- inner = TREE_OPERAND (inner, 0);
+ || TREE_CODE (inner) == SAVE_EXPR)
+ inner = TREE_OPERAND (inner, 0);
if (! DECL_P (inner))
inner = NULL_TREE;
@@ -1516,8 +1383,8 @@ component_ref_for_mem_expr (tree ref)
if (inner == TREE_OPERAND (ref, 0))
return ref;
else
- return build (COMPONENT_REF, TREE_TYPE (ref), inner,
- TREE_OPERAND (ref, 1));
+ return build3 (COMPONENT_REF, TREE_TYPE (ref), inner,
+ TREE_OPERAND (ref, 1), NULL_TREE);
}
/* Returns 1 if both MEM_EXPR can be considered equal
@@ -1542,16 +1409,16 @@ mem_expr_equal_p (tree expr1, tree expr2)
&& mem_expr_equal_p (TREE_OPERAND (expr1, 1), /* field decl */
TREE_OPERAND (expr2, 1));
- if (TREE_CODE (expr1) == INDIRECT_REF)
+ if (INDIRECT_REF_P (expr1))
return mem_expr_equal_p (TREE_OPERAND (expr1, 0),
TREE_OPERAND (expr2, 0));
-
- /* Decls with different pointers can't be equal. */
- if (DECL_P (expr1))
- return 0;
- abort(); /* ARRAY_REFs, ARRAY_RANGE_REFs and BIT_FIELD_REFs should already
+ /* ARRAY_REFs, ARRAY_RANGE_REFs and BIT_FIELD_REFs should already
have been resolved here. */
+ gcc_assert (DECL_P (expr1));
+
+ /* Decls with different pointers can't be equal. */
+ return 0;
}
/* Given REF, a MEM, and T, either the type of X or the expression
@@ -1585,19 +1452,15 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
wrong answer, as it assumes that DECL_RTL already has the right alias
info. Callers should not set DECL_RTL until after the call to
set_mem_attributes. */
- if (DECL_P (t) && ref == DECL_RTL_IF_SET (t))
- abort ();
+ gcc_assert (!DECL_P (t) || ref != DECL_RTL_IF_SET (t));
/* Get the alias set from the expression or type (perhaps using a
front-end routine) and use it. */
alias = get_alias_set (t);
- MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
+ MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type);
MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
- RTX_UNCHANGING_P (ref)
- |= ((lang_hooks.honor_readonly
- && (TYPE_READONLY (type) || TREE_READONLY (t)))
- || (! TYPE_P (t) && TREE_CONSTANT (t)));
+ MEM_POINTER (ref) = POINTER_TYPE_P (type);
/* If we are making an object of this type, or if this is a DECL, we know
that it is a scalar if the type is not an aggregate. */
@@ -1606,8 +1469,19 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
/* We can set the alignment from the type if we are making an object,
this is an INDIRECT_REF, or if TYPE_ALIGN_OK. */
- if (objectp || TREE_CODE (t) == INDIRECT_REF || TYPE_ALIGN_OK (type))
+ if (objectp || TREE_CODE (t) == INDIRECT_REF
+ || TREE_CODE (t) == ALIGN_INDIRECT_REF
+ || TYPE_ALIGN_OK (type))
align = MAX (align, TYPE_ALIGN (type));
+ else
+ if (TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+ {
+ if (integer_zerop (TREE_OPERAND (t, 1)))
+ /* We don't know anything about the alignment. */
+ align = BITS_PER_UNIT;
+ else
+ align = tree_low_cst (TREE_OPERAND (t, 1), 1);
+ }
/* If the size is known, we can set that. */
if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
@@ -1617,7 +1491,8 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
the expression. */
if (! TYPE_P (t))
{
- maybe_set_unchanging (ref, t);
+ tree base;
+
if (TREE_THIS_VOLATILE (t))
MEM_VOLATILE_P (ref) = 1;
@@ -1629,9 +1504,39 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
|| TREE_CODE (t) == SAVE_EXPR)
t = TREE_OPERAND (t, 0);
- /* If this expression can't be addressed (e.g., it contains a reference
- to a non-addressable field), show we don't change its alias set. */
- if (! can_address_p (t))
+ /* We may look through structure-like accesses for the purposes of
+ examining TREE_THIS_NOTRAP, but not array-like accesses. */
+ base = t;
+ while (TREE_CODE (base) == COMPONENT_REF
+ || TREE_CODE (base) == REALPART_EXPR
+ || TREE_CODE (base) == IMAGPART_EXPR
+ || TREE_CODE (base) == BIT_FIELD_REF)
+ base = TREE_OPERAND (base, 0);
+
+ if (DECL_P (base))
+ {
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (base), TS_DECL_WITH_VIS))
+ MEM_NOTRAP_P (ref) = !DECL_WEAK (base);
+ else
+ MEM_NOTRAP_P (ref) = 1;
+ }
+ else
+ MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (base);
+
+ base = get_base_address (base);
+ if (base && DECL_P (base)
+ && TREE_READONLY (base)
+ && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
+ {
+ tree base_type = TREE_TYPE (base);
+ gcc_assert (!(base_type && TYPE_NEEDS_CONSTRUCTING (base_type))
+ || DECL_ARTIFICIAL (base));
+ MEM_READONLY_P (ref) = 1;
+ }
+
+ /* If this expression uses it's parent's alias set, mark it such
+ that we won't change it. */
+ if (component_uses_parent_alias_set (t))
MEM_KEEP_ALIAS_SET_P (ref) = 1;
/* If this is a decl, set the attributes of the MEM from it. */
@@ -1647,7 +1552,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
}
/* If this is a constant, we know the alignment. */
- else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
+ else if (CONSTANT_CLASS_P (t))
{
align = TYPE_ALIGN (type);
#ifdef CONSTANT_ALIGNMENT
@@ -1680,34 +1585,23 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
do
{
tree index = TREE_OPERAND (t2, 1);
- tree array = TREE_OPERAND (t2, 0);
- tree domain = TYPE_DOMAIN (TREE_TYPE (array));
- tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
- tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
+ tree low_bound = array_ref_low_bound (t2);
+ tree unit_size = array_ref_element_size (t2);
/* We assume all arrays have sizes that are a multiple of a byte.
First subtract the lower bound, if any, in the type of the
- index, then convert to sizetype and multiply by the size of the
- array element. */
- if (low_bound != 0 && ! integer_zerop (low_bound))
- index = fold (build (MINUS_EXPR, TREE_TYPE (index),
- index, low_bound));
-
- /* If the index has a self-referential type, pass it to a
- WITH_RECORD_EXPR; if the component size is, pass our
- component to one. */
- if (CONTAINS_PLACEHOLDER_P (index))
- index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t2);
- if (CONTAINS_PLACEHOLDER_P (unit_size))
- unit_size = build (WITH_RECORD_EXPR, sizetype,
- unit_size, array);
-
- off_tree
- = fold (build (PLUS_EXPR, sizetype,
- fold (build (MULT_EXPR, sizetype,
- index,
- unit_size)),
- off_tree));
+ index, then convert to sizetype and multiply by the size of
+ the array element. */
+ if (! integer_zerop (low_bound))
+ index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
+ index, low_bound);
+
+ off_tree = size_binop (PLUS_EXPR,
+ size_binop (MULT_EXPR,
+ fold_convert (sizetype,
+ index),
+ unit_size),
+ off_tree);
t2 = TREE_OPERAND (t2, 0);
}
while (TREE_CODE (t2) == ARRAY_REF);
@@ -1739,7 +1633,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
the size we got from the type? */
}
else if (flag_argument_noalias > 1
- && TREE_CODE (t2) == INDIRECT_REF
+ && (INDIRECT_REF_P (t2))
&& TREE_CODE (TREE_OPERAND (t2, 0)) == PARM_DECL)
{
expr = t2;
@@ -1750,7 +1644,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
/* If this is a Fortran indirect argument reference, record the
parameter decl. */
else if (flag_argument_noalias > 1
- && TREE_CODE (t) == INDIRECT_REF
+ && (INDIRECT_REF_P (t))
&& TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL)
{
expr = t;
@@ -1768,6 +1662,14 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
size = plus_constant (size, apply_bitpos / BITS_PER_UNIT);
}
+ if (TREE_CODE (t) == ALIGN_INDIRECT_REF)
+ {
+ /* Force EXPR and OFFSE to NULL, since we don't know exactly what
+ we're overlapping. */
+ offset = NULL;
+ expr = NULL;
+ }
+
/* Now set the attributes we computed above. */
MEM_ATTRS (ref)
= get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref));
@@ -1808,8 +1710,7 @@ set_mem_alias_set (rtx mem, HOST_WIDE_INT set)
{
#ifdef ENABLE_CHECKING
/* If the new and old alias sets don't conflict, something is wrong. */
- if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
- abort ();
+ gcc_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)));
#endif
MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
@@ -1868,8 +1769,7 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
{
rtx new;
- if (GET_CODE (memref) != MEM)
- abort ();
+ gcc_assert (MEM_P (memref));
if (mode == VOIDmode)
mode = GET_MODE (memref);
if (addr == 0)
@@ -1881,10 +1781,7 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
if (validate)
{
if (reload_in_progress || reload_completed)
- {
- if (! memory_address_p (mode, addr))
- abort ();
- }
+ gcc_assert (memory_address_p (mode, addr));
else
addr = memory_address (mode, addr);
}
@@ -2103,6 +2000,7 @@ widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset)
if (TREE_CODE (expr) == COMPONENT_REF)
{
tree field = TREE_OPERAND (expr, 1);
+ tree offset = component_ref_field_offset (expr);
if (! DECL_SIZE_UNIT (field))
{
@@ -2117,17 +2015,18 @@ widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset)
&& INTVAL (memoffset) >= 0)
break;
- if (! host_integerp (DECL_FIELD_OFFSET (field), 1))
+ if (! host_integerp (offset, 1))
{
expr = NULL_TREE;
break;
}
expr = TREE_OPERAND (expr, 0);
- memoffset = (GEN_INT (INTVAL (memoffset)
- + tree_low_cst (DECL_FIELD_OFFSET (field), 1)
- + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
- / BITS_PER_UNIT)));
+ memoffset
+ = (GEN_INT (INTVAL (memoffset)
+ + tree_low_cst (offset, 1)
+ + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+ / BITS_PER_UNIT)));
}
/* Similarly for the decl. */
else if (DECL_P (expr)
@@ -2186,31 +2085,12 @@ set_new_first_and_last_insn (rtx first, rtx last)
cur_insn_uid++;
}
-
-/* Set the last label number found in the current function.
- This is used when belatedly compiling an inline function. */
-
-void
-set_new_last_label_num (int last)
-{
- base_label_num = label_num;
- last_label_num = last;
-}
-
-/* Restore all variables describing the current status from the structure *P.
- This is used after a nested function. */
-
-void
-restore_emit_status (struct function *p ATTRIBUTE_UNUSED)
-{
- last_label_num = 0;
-}
/* Go through all the RTL insn bodies and copy any invalid shared
structure. This routine should only be called once. */
-void
-unshare_all_rtl (tree fndecl, rtx insn)
+static void
+unshare_all_rtl_1 (tree fndecl, rtx insn)
{
tree decl;
@@ -2261,9 +2141,34 @@ unshare_all_rtl_again (rtx insn)
reset_used_flags (stack_slot_list);
- unshare_all_rtl (cfun->decl, insn);
+ unshare_all_rtl_1 (cfun->decl, insn);
+}
+
+unsigned int
+unshare_all_rtl (void)
+{
+ unshare_all_rtl_1 (current_function_decl, get_insns ());
+ return 0;
}
+struct tree_opt_pass pass_unshare_all_rtl =
+{
+ "unshare", /* name */
+ NULL, /* gate */
+ unshare_all_rtl, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
+
+
/* Check that ORIG is not marked when it should not be and mark ORIG as in use,
Recursively does the same for subexpressions. */
@@ -2285,7 +2190,6 @@ verify_rtx_sharing (rtx orig, rtx insn)
switch (code)
{
case REG:
- case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
case CONST_VECTOR:
@@ -2295,8 +2199,12 @@ verify_rtx_sharing (rtx orig, rtx insn)
case PC:
case CC0:
case SCRATCH:
- /* SCRATCH must be shared because they represent distinct values. */
return;
+ /* SCRATCH must be shared because they represent distinct values. */
+ case CLOBBER:
+ if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
+ return;
+ break;
case CONST:
/* CONST can be shared if it contains a SYMBOL_REF. If it contains
@@ -2321,15 +2229,18 @@ verify_rtx_sharing (rtx orig, rtx insn)
/* This rtx may not be shared. If it has already been seen,
replace it with a copy of itself. */
-
+#ifdef ENABLE_CHECKING
if (RTX_FLAG (x, used))
{
- error ("Invalid rtl sharing found in the insn");
+ error ("invalid rtl sharing found in the insn");
debug_rtx (insn);
- error ("Shared rtx");
+ error ("shared rtx");
debug_rtx (x);
- abort ();
+ internal_error ("internal consistency failure");
}
+#endif
+ gcc_assert (!RTX_FLAG (x, used));
+
RTX_FLAG (x, used) = 1;
/* Now scan the subexpressions recursively. */
@@ -2352,9 +2263,11 @@ verify_rtx_sharing (rtx orig, rtx insn)
for (j = 0; j < len; j++)
{
- /* We allow sharing of ASM_OPERANDS inside single instruction. */
+ /* We allow sharing of ASM_OPERANDS inside single
+ instruction. */
if (j && GET_CODE (XVECEXP (x, i, j)) == SET
- && GET_CODE (SET_SRC (XVECEXP (x, i, j))) == ASM_OPERANDS)
+ && (GET_CODE (SET_SRC (XVECEXP (x, i, j)))
+ == ASM_OPERANDS))
verify_rtx_sharing (SET_DEST (XVECEXP (x, i, j)), insn);
else
verify_rtx_sharing (XVECEXP (x, i, j), insn);
@@ -2440,106 +2353,6 @@ reset_used_decls (tree blk)
reset_used_decls (t);
}
-/* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
- placed in the result directly, rather than being copied. MAY_SHARE is
- either a MEM of an EXPR_LIST of MEMs. */
-
-rtx
-copy_most_rtx (rtx orig, rtx may_share)
-{
- rtx copy;
- int i, j;
- RTX_CODE code;
- const char *format_ptr;
-
- if (orig == may_share
- || (GET_CODE (may_share) == EXPR_LIST
- && in_expr_list_p (may_share, orig)))
- return orig;
-
- code = GET_CODE (orig);
-
- switch (code)
- {
- case REG:
- case QUEUED:
- case CONST_INT:
- case CONST_DOUBLE:
- case CONST_VECTOR:
- case SYMBOL_REF:
- case CODE_LABEL:
- case PC:
- case CC0:
- return orig;
- default:
- break;
- }
-
- copy = rtx_alloc (code);
- PUT_MODE (copy, GET_MODE (orig));
- RTX_FLAG (copy, in_struct) = RTX_FLAG (orig, in_struct);
- RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
- RTX_FLAG (copy, unchanging) = RTX_FLAG (orig, unchanging);
- RTX_FLAG (copy, integrated) = RTX_FLAG (orig, integrated);
- RTX_FLAG (copy, frame_related) = RTX_FLAG (orig, frame_related);
-
- format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
-
- for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
- {
- switch (*format_ptr++)
- {
- case 'e':
- XEXP (copy, i) = XEXP (orig, i);
- if (XEXP (orig, i) != NULL && XEXP (orig, i) != may_share)
- XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
- break;
-
- case 'u':
- XEXP (copy, i) = XEXP (orig, i);
- break;
-
- case 'E':
- case 'V':
- XVEC (copy, i) = XVEC (orig, i);
- if (XVEC (orig, i) != NULL)
- {
- XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
- for (j = 0; j < XVECLEN (copy, i); j++)
- XVECEXP (copy, i, j)
- = copy_most_rtx (XVECEXP (orig, i, j), may_share);
- }
- break;
-
- case 'w':
- XWINT (copy, i) = XWINT (orig, i);
- break;
-
- case 'n':
- case 'i':
- XINT (copy, i) = XINT (orig, i);
- break;
-
- case 't':
- XTREE (copy, i) = XTREE (orig, i);
- break;
-
- case 's':
- case 'S':
- XSTR (copy, i) = XSTR (orig, i);
- break;
-
- case '0':
- X0ANY (copy, i) = X0ANY (orig, i);
- break;
-
- default:
- abort ();
- }
- }
- return copy;
-}
-
/* Mark ORIG as in use, and return a copy of it if it was already in use.
Recursively does the same for subexpressions. Uses
copy_rtx_if_shared_1 to reduce stack space. */
@@ -2579,7 +2392,6 @@ repeat:
switch (code)
{
case REG:
- case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
case CONST_VECTOR:
@@ -2591,6 +2403,10 @@ repeat:
case SCRATCH:
/* SCRATCH must be shared because they represent distinct values. */
return;
+ case CLOBBER:
+ if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
+ return;
+ break;
case CONST:
/* CONST can be shared if it contains a SYMBOL_REF. If it contains
@@ -2618,11 +2434,7 @@ repeat:
if (RTX_FLAG (x, used))
{
- rtx copy;
-
- copy = rtx_alloc (code);
- memcpy (copy, x, RTX_SIZE (code));
- x = copy;
+ x = shallow_copy_rtx (x);
copied = 1;
}
RTX_FLAG (x, used) = 1;
@@ -2701,7 +2513,6 @@ repeat:
switch (code)
{
case REG:
- case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
case CONST_VECTOR:
@@ -2771,7 +2582,6 @@ set_used_flags (rtx x)
switch (code)
{
case REG:
- case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
case CONST_VECTOR:
@@ -2835,11 +2645,11 @@ make_safe_from (rtx x, rtx other)
goto done;
}
done:
- if ((GET_CODE (other) == MEM
+ if ((MEM_P (other)
&& ! CONSTANT_P (x)
- && GET_CODE (x) != REG
+ && !REG_P (x)
&& GET_CODE (x) != SUBREG)
- || (GET_CODE (other) == REG
+ || (REG_P (other)
&& (REGNO (other) < FIRST_PSEUDO_REGISTER
|| reg_mentioned_p (other, x))))
{
@@ -2865,8 +2675,7 @@ get_insns (void)
void
set_first_insn (rtx insn)
{
- if (PREV_INSN (insn) != 0)
- abort ();
+ gcc_assert (!PREV_INSN (insn));
first_insn = insn;
}
@@ -2883,8 +2692,7 @@ get_last_insn (void)
void
set_last_insn (rtx insn)
{
- if (NEXT_INSN (insn) != 0)
- abort ();
+ gcc_assert (!NEXT_INSN (insn));
last_insn = insn;
}
@@ -2919,7 +2727,7 @@ get_first_nonnote_insn (void)
continue;
else
{
- if (GET_CODE (insn) == INSN
+ if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
insn = XVECEXP (PATTERN (insn), 0, 0);
}
@@ -2945,7 +2753,7 @@ get_last_nonnote_insn (void)
continue;
else
{
- if (GET_CODE (insn) == INSN
+ if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
insn = XVECEXP (PATTERN (insn), 0,
XVECLEN (PATTERN (insn), 0) - 1);
@@ -2966,7 +2774,7 @@ get_max_uid (void)
/* Renumber instructions so that no instruction UIDs are wasted. */
void
-renumber_insns (FILE *stream)
+renumber_insns (void)
{
rtx insn;
@@ -2983,8 +2791,8 @@ renumber_insns (FILE *stream)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if (stream)
- fprintf (stream, "Renumbering insn %d to %d\n",
+ if (dump_file)
+ fprintf (dump_file, "Renumbering insn %d to %d\n",
INSN_UID (insn), cur_insn_uid);
INSN_UID (insn) = cur_insn_uid++;
}
@@ -2999,7 +2807,7 @@ next_insn (rtx insn)
if (insn)
{
insn = NEXT_INSN (insn);
- if (insn && GET_CODE (insn) == INSN
+ if (insn && NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
insn = XVECEXP (PATTERN (insn), 0, 0);
}
@@ -3016,7 +2824,7 @@ previous_insn (rtx insn)
if (insn)
{
insn = PREV_INSN (insn);
- if (insn && GET_CODE (insn) == INSN
+ if (insn && NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1);
}
@@ -3033,7 +2841,7 @@ next_nonnote_insn (rtx insn)
while (insn)
{
insn = NEXT_INSN (insn);
- if (insn == 0 || GET_CODE (insn) != NOTE)
+ if (insn == 0 || !NOTE_P (insn))
break;
}
@@ -3049,7 +2857,7 @@ prev_nonnote_insn (rtx insn)
while (insn)
{
insn = PREV_INSN (insn);
- if (insn == 0 || GET_CODE (insn) != NOTE)
+ if (insn == 0 || !NOTE_P (insn))
break;
}
@@ -3066,8 +2874,7 @@ next_real_insn (rtx insn)
while (insn)
{
insn = NEXT_INSN (insn);
- if (insn == 0 || GET_CODE (insn) == INSN
- || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
+ if (insn == 0 || INSN_P (insn))
break;
}
@@ -3084,8 +2891,7 @@ prev_real_insn (rtx insn)
while (insn)
{
insn = PREV_INSN (insn);
- if (insn == 0 || GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
- || GET_CODE (insn) == JUMP_INSN)
+ if (insn == 0 || INSN_P (insn))
break;
}
@@ -3101,7 +2907,7 @@ last_call_insn (void)
rtx insn;
for (insn = get_last_insn ();
- insn && GET_CODE (insn) != CALL_INSN;
+ insn && !CALL_P (insn);
insn = PREV_INSN (insn))
;
@@ -3115,8 +2921,8 @@ last_call_insn (void)
int
active_insn_p (rtx insn)
{
- return (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
- || (GET_CODE (insn) == INSN
+ return (CALL_P (insn) || JUMP_P (insn)
+ || (NONJUMP_INSN_P (insn)
&& (! reload_completed
|| (GET_CODE (PATTERN (insn)) != USE
&& GET_CODE (PATTERN (insn)) != CLOBBER))));
@@ -3160,7 +2966,7 @@ next_label (rtx insn)
while (insn)
{
insn = NEXT_INSN (insn);
- if (insn == 0 || GET_CODE (insn) == CODE_LABEL)
+ if (insn == 0 || LABEL_P (insn))
break;
}
@@ -3175,12 +2981,27 @@ prev_label (rtx insn)
while (insn)
{
insn = PREV_INSN (insn);
- if (insn == 0 || GET_CODE (insn) == CODE_LABEL)
+ if (insn == 0 || LABEL_P (insn))
break;
}
return insn;
}
+
+/* Return the last label to mark the same position as LABEL. Return null
+ if LABEL itself is null. */
+
+rtx
+skip_consecutive_labels (rtx label)
+{
+ rtx insn;
+
+ for (insn = label; insn != 0 && !INSN_P (insn); insn = NEXT_INSN (insn))
+ if (LABEL_P (insn))
+ label = insn;
+
+ return label;
+}
#ifdef HAVE_cc0
/* INSN uses CC0 and is being moved into a delay slot. Set up REG_CC_SETTER
@@ -3191,7 +3012,7 @@ link_cc0_insns (rtx insn)
{
rtx user = next_nonnote_insn (insn);
- if (GET_CODE (user) == INSN && GET_CODE (PATTERN (user)) == SEQUENCE)
+ if (NONJUMP_INSN_P (user) && GET_CODE (PATTERN (user)) == SEQUENCE)
user = XVECEXP (PATTERN (user), 0, 0);
REG_NOTES (user) = gen_rtx_INSN_LIST (REG_CC_SETTER, insn,
@@ -3217,7 +3038,7 @@ next_cc0_user (rtx insn)
return XEXP (note, 0);
insn = next_nonnote_insn (insn);
- if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ if (insn && NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
insn = XVECEXP (PATTERN (insn), 0, 0);
if (insn && INSN_P (insn) && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
@@ -3238,8 +3059,7 @@ prev_cc0_setter (rtx insn)
return XEXP (note, 0);
insn = prev_nonnote_insn (insn);
- if (! sets_cc0_p (PATTERN (insn)))
- abort ();
+ gcc_assert (sets_cc0_p (PATTERN (insn)));
return insn;
}
@@ -3302,7 +3122,7 @@ try_split (rtx pat, rtx trial, int last)
/* If we are splitting a JUMP_INSN, it might be followed by a BARRIER.
We may need to handle this specially. */
- if (after && GET_CODE (after) == BARRIER)
+ if (after && BARRIER_P (after))
{
has_barrier = 1;
after = NEXT_INSN (after);
@@ -3327,7 +3147,7 @@ try_split (rtx pat, rtx trial, int last)
/* Mark labels. */
for (insn = insn_last; insn ; insn = PREV_INSN (insn))
{
- if (GET_CODE (insn) == JUMP_INSN)
+ if (JUMP_P (insn))
{
mark_jump_label (PATTERN (insn), insn, 0);
njumps++;
@@ -3339,8 +3159,7 @@ try_split (rtx pat, rtx trial, int last)
one jump is created, otherwise the machine description
is responsible for this step using
split_branch_probability variable. */
- if (njumps != 1)
- abort ();
+ gcc_assert (njumps == 1);
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_BR_PROB,
GEN_INT (probability),
@@ -3351,10 +3170,10 @@ try_split (rtx pat, rtx trial, int last)
/* If we are splitting a CALL_INSN, look for the CALL_INSN
in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */
- if (GET_CODE (trial) == CALL_INSN)
+ if (CALL_P (trial))
{
for (insn = insn_last; insn ; insn = PREV_INSN (insn))
- if (GET_CODE (insn) == CALL_INSN)
+ if (CALL_P (insn))
{
rtx *p = &CALL_INSN_FUNCTION_USAGE (insn);
while (*p)
@@ -3373,8 +3192,8 @@ try_split (rtx pat, rtx trial, int last)
insn = insn_last;
while (insn != NULL_RTX)
{
- if (GET_CODE (insn) == CALL_INSN
- || (flag_non_call_exceptions
+ if (CALL_P (insn)
+ || (flag_non_call_exceptions && INSN_P (insn)
&& may_trap_p (PATTERN (insn))))
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_EH_REGION,
@@ -3386,11 +3205,10 @@ try_split (rtx pat, rtx trial, int last)
case REG_NORETURN:
case REG_SETJMP:
- case REG_ALWAYS_RETURN:
insn = insn_last;
while (insn != NULL_RTX)
{
- if (GET_CODE (insn) == CALL_INSN)
+ if (CALL_P (insn))
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
XEXP (note, 0),
@@ -3403,7 +3221,7 @@ try_split (rtx pat, rtx trial, int last)
insn = insn_last;
while (insn != NULL_RTX)
{
- if (GET_CODE (insn) == JUMP_INSN)
+ if (JUMP_P (insn))
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
XEXP (note, 0),
@@ -3419,12 +3237,12 @@ try_split (rtx pat, rtx trial, int last)
/* If there are LABELS inside the split insns increment the
usage count so we don't delete the label. */
- if (GET_CODE (trial) == INSN)
+ if (NONJUMP_INSN_P (trial))
{
insn = insn_last;
while (insn != NULL_RTX)
{
- if (GET_CODE (insn) == INSN)
+ if (NONJUMP_INSN_P (insn))
mark_label_nuses (PATTERN (insn));
insn = PREV_INSN (insn);
@@ -3478,7 +3296,7 @@ make_insn_raw (rtx pattern)
|| (GET_CODE (insn) == SET
&& SET_DEST (insn) == pc_rtx)))
{
- warning ("ICE: emit_insn used where emit_jump_insn needed:\n");
+ warning (0, "ICE: emit_insn used where emit_jump_insn needed:\n");
debug_rtx (insn);
}
#endif
@@ -3488,7 +3306,7 @@ make_insn_raw (rtx pattern)
/* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */
-static rtx
+rtx
make_jump_insn_raw (rtx pattern)
{
rtx insn;
@@ -3557,8 +3375,7 @@ add_insn_after (rtx insn, rtx after)
rtx next = NEXT_INSN (after);
basic_block bb;
- if (optimize && INSN_DELETED_P (after))
- abort ();
+ gcc_assert (!optimize || !INSN_DELETED_P (after));
NEXT_INSN (insn) = next;
PREV_INSN (insn) = after;
@@ -3566,7 +3383,7 @@ add_insn_after (rtx insn, rtx after)
if (next)
{
PREV_INSN (next) = insn;
- if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE)
+ if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn;
}
else if (last_insn == after)
@@ -3582,12 +3399,11 @@ add_insn_after (rtx insn, rtx after)
break;
}
- if (stack == 0)
- abort ();
+ gcc_assert (stack);
}
- if (GET_CODE (after) != BARRIER
- && GET_CODE (insn) != BARRIER
+ if (!BARRIER_P (after)
+ && !BARRIER_P (insn)
&& (bb = BLOCK_FOR_INSN (after)))
{
set_block_for_insn (insn, bb);
@@ -3597,14 +3413,14 @@ add_insn_after (rtx insn, rtx after)
either NOTE or LABEL. */
if (BB_END (bb) == after
/* Avoid clobbering of structure when creating new BB. */
- && GET_CODE (insn) != BARRIER
- && (GET_CODE (insn) != NOTE
+ && !BARRIER_P (insn)
+ && (!NOTE_P (insn)
|| NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
BB_END (bb) = insn;
}
NEXT_INSN (after) = insn;
- if (GET_CODE (after) == INSN && GET_CODE (PATTERN (after)) == SEQUENCE)
+ if (NONJUMP_INSN_P (after) && GET_CODE (PATTERN (after)) == SEQUENCE)
{
rtx sequence = PATTERN (after);
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
@@ -3622,8 +3438,7 @@ add_insn_before (rtx insn, rtx before)
rtx prev = PREV_INSN (before);
basic_block bb;
- if (optimize && INSN_DELETED_P (before))
- abort ();
+ gcc_assert (!optimize || !INSN_DELETED_P (before));
PREV_INSN (insn) = prev;
NEXT_INSN (insn) = before;
@@ -3631,7 +3446,7 @@ add_insn_before (rtx insn, rtx before)
if (prev)
{
NEXT_INSN (prev) = insn;
- if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE)
+ if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
{
rtx sequence = PATTERN (prev);
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
@@ -3650,29 +3465,27 @@ add_insn_before (rtx insn, rtx before)
break;
}
- if (stack == 0)
- abort ();
+ gcc_assert (stack);
}
- if (GET_CODE (before) != BARRIER
- && GET_CODE (insn) != BARRIER
+ if (!BARRIER_P (before)
+ && !BARRIER_P (insn)
&& (bb = BLOCK_FOR_INSN (before)))
{
set_block_for_insn (insn, bb);
if (INSN_P (insn))
bb->flags |= BB_DIRTY;
- /* Should not happen as first in the BB is always
- either NOTE or LABEl. */
- if (BB_HEAD (bb) == insn
- /* Avoid clobbering of structure when creating new BB. */
- && GET_CODE (insn) != BARRIER
- && (GET_CODE (insn) != NOTE
- || NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
- abort ();
+ /* Should not happen as first in the BB is always either NOTE or
+ LABEL. */
+ gcc_assert (BB_HEAD (bb) != insn
+ /* Avoid clobbering of structure when creating new BB. */
+ || BARRIER_P (insn)
+ || (NOTE_P (insn)
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK));
}
PREV_INSN (before) = insn;
- if (GET_CODE (before) == INSN && GET_CODE (PATTERN (before)) == SEQUENCE)
+ if (NONJUMP_INSN_P (before) && GET_CODE (PATTERN (before)) == SEQUENCE)
PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn;
}
@@ -3688,7 +3501,7 @@ remove_insn (rtx insn)
if (prev)
{
NEXT_INSN (prev) = next;
- if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE)
+ if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
{
rtx sequence = PATTERN (prev);
NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = next;
@@ -3707,14 +3520,13 @@ remove_insn (rtx insn)
break;
}
- if (stack == 0)
- abort ();
+ gcc_assert (stack);
}
if (next)
{
PREV_INSN (next) = prev;
- if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE)
+ if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev;
}
else if (last_insn == insn)
@@ -3730,10 +3542,9 @@ remove_insn (rtx insn)
break;
}
- if (stack == 0)
- abort ();
+ gcc_assert (stack);
}
- if (GET_CODE (insn) != BARRIER
+ if (!BARRIER_P (insn)
&& (bb = BLOCK_FOR_INSN (insn)))
{
if (INSN_P (insn))
@@ -3742,8 +3553,7 @@ remove_insn (rtx insn)
{
/* Never ever delete the basic block note without deleting whole
basic block. */
- if (GET_CODE (insn) == NOTE)
- abort ();
+ gcc_assert (!NOTE_P (insn));
BB_HEAD (bb) = next;
}
if (BB_END (bb) == insn)
@@ -3756,8 +3566,7 @@ remove_insn (rtx insn)
void
add_function_usage_to (rtx call_insn, rtx call_fusage)
{
- if (! call_insn || GET_CODE (call_insn) != CALL_INSN)
- abort ();
+ gcc_assert (call_insn && CALL_P (call_insn));
/* Put the register usage information on the CALL. If there is already
some usage information, put ours at the end. */
@@ -3831,13 +3640,13 @@ reorder_insns (rtx from, rtx to, rtx after)
reorder_insns_nobb (from, to, after);
- if (GET_CODE (after) != BARRIER
+ if (!BARRIER_P (after)
&& (bb = BLOCK_FOR_INSN (after)))
{
rtx x;
bb->flags |= BB_DIRTY;
- if (GET_CODE (from) != BARRIER
+ if (!BARRIER_P (from)
&& (bb2 = BLOCK_FOR_INSN (from)))
{
if (BB_END (bb2) == to)
@@ -3849,7 +3658,8 @@ reorder_insns (rtx from, rtx to, rtx after)
BB_END (bb) = to;
for (x = from; x != NEXT_INSN (to); x = NEXT_INSN (x))
- set_block_for_insn (x, bb);
+ if (!BARRIER_P (x))
+ set_block_for_insn (x, bb);
}
}
@@ -3862,146 +3672,13 @@ find_line_note (rtx insn)
return 0;
for (; insn; insn = PREV_INSN (insn))
- if (GET_CODE (insn) == NOTE
+ if (NOTE_P (insn)
&& NOTE_LINE_NUMBER (insn) >= 0)
break;
return insn;
}
-/* Like reorder_insns, but inserts line notes to preserve the line numbers
- of the moved insns when debugging. This may insert a note between AFTER
- and FROM, and another one after TO. */
-
-void
-reorder_insns_with_line_notes (rtx from, rtx to, rtx after)
-{
- rtx from_line = find_line_note (from);
- rtx after_line = find_line_note (after);
-
- reorder_insns (from, to, after);
-
- if (from_line == after_line)
- return;
-
- if (from_line)
- emit_note_copy_after (from_line, after);
- if (after_line)
- emit_note_copy_after (after_line, to);
-}
-
-/* Remove unnecessary notes from the instruction stream. */
-
-void
-remove_unnecessary_notes (void)
-{
- rtx block_stack = NULL_RTX;
- rtx eh_stack = NULL_RTX;
- rtx insn;
- rtx next;
- rtx tmp;
-
- /* We must not remove the first instruction in the function because
- the compiler depends on the first instruction being a note. */
- for (insn = NEXT_INSN (get_insns ()); insn; insn = next)
- {
- /* Remember what's next. */
- next = NEXT_INSN (insn);
-
- /* We're only interested in notes. */
- if (GET_CODE (insn) != NOTE)
- continue;
-
- switch (NOTE_LINE_NUMBER (insn))
- {
- case NOTE_INSN_DELETED:
- case NOTE_INSN_LOOP_END_TOP_COND:
- remove_insn (insn);
- break;
-
- case NOTE_INSN_EH_REGION_BEG:
- eh_stack = alloc_INSN_LIST (insn, eh_stack);
- break;
-
- case NOTE_INSN_EH_REGION_END:
- /* Too many end notes. */
- if (eh_stack == NULL_RTX)
- abort ();
- /* Mismatched nesting. */
- if (NOTE_EH_HANDLER (XEXP (eh_stack, 0)) != NOTE_EH_HANDLER (insn))
- abort ();
- tmp = eh_stack;
- eh_stack = XEXP (eh_stack, 1);
- free_INSN_LIST_node (tmp);
- break;
-
- case NOTE_INSN_BLOCK_BEG:
- /* By now, all notes indicating lexical blocks should have
- NOTE_BLOCK filled in. */
- if (NOTE_BLOCK (insn) == NULL_TREE)
- abort ();
- block_stack = alloc_INSN_LIST (insn, block_stack);
- break;
-
- case NOTE_INSN_BLOCK_END:
- /* Too many end notes. */
- if (block_stack == NULL_RTX)
- abort ();
- /* Mismatched nesting. */
- if (NOTE_BLOCK (XEXP (block_stack, 0)) != NOTE_BLOCK (insn))
- abort ();
- tmp = block_stack;
- block_stack = XEXP (block_stack, 1);
- free_INSN_LIST_node (tmp);
-
- /* Scan back to see if there are any non-note instructions
- between INSN and the beginning of this block. If not,
- then there is no PC range in the generated code that will
- actually be in this block, so there's no point in
- remembering the existence of the block. */
- for (tmp = PREV_INSN (insn); tmp; tmp = PREV_INSN (tmp))
- {
- /* This block contains a real instruction. Note that we
- don't include labels; if the only thing in the block
- is a label, then there are still no PC values that
- lie within the block. */
- if (INSN_P (tmp))
- break;
-
- /* We're only interested in NOTEs. */
- if (GET_CODE (tmp) != NOTE)
- continue;
-
- if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_BEG)
- {
- /* We just verified that this BLOCK matches us with
- the block_stack check above. Never delete the
- BLOCK for the outermost scope of the function; we
- can refer to names from that scope even if the
- block notes are messed up. */
- if (! is_body_block (NOTE_BLOCK (insn))
- && (*debug_hooks->ignore_block) (NOTE_BLOCK (insn)))
- {
- remove_insn (tmp);
- remove_insn (insn);
- }
- break;
- }
- else if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_END)
- /* There's a nested block. We need to leave the
- current block in place since otherwise the debugger
- wouldn't be able to show symbols from our block in
- the nested block. */
- break;
- }
- }
- }
-
- /* Too many begin notes. */
- if (block_stack || eh_stack)
- abort ();
-}
-
/* Emit insn(s) of given code and pattern
at a specified place within the doubly-linked list.
@@ -4036,10 +3713,7 @@ emit_insn_before_noloc (rtx x, rtx before)
rtx last = before;
rtx insn;
-#ifdef ENABLE_RTL_CHECKING
- if (before == NULL_RTX)
- abort ();
-#endif
+ gcc_assert (before);
if (x == NULL_RTX)
return last;
@@ -4064,7 +3738,7 @@ emit_insn_before_noloc (rtx x, rtx before)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4085,10 +3759,7 @@ emit_jump_insn_before_noloc (rtx x, rtx before)
{
rtx insn, last = NULL_RTX;
-#ifdef ENABLE_RTL_CHECKING
- if (before == NULL_RTX)
- abort ();
-#endif
+ gcc_assert (before);
switch (GET_CODE (x))
{
@@ -4110,7 +3781,7 @@ emit_jump_insn_before_noloc (rtx x, rtx before)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4131,10 +3802,7 @@ emit_call_insn_before_noloc (rtx x, rtx before)
{
rtx last = NULL_RTX, insn;
-#ifdef ENABLE_RTL_CHECKING
- if (before == NULL_RTX)
- abort ();
-#endif
+ gcc_assert (before);
switch (GET_CODE (x))
{
@@ -4156,7 +3824,7 @@ emit_call_insn_before_noloc (rtx x, rtx before)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4206,7 +3874,9 @@ emit_note_before (int subtype, rtx before)
{
rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
+#ifndef USE_MAPPED_LOCATION
NOTE_SOURCE_FILE (note) = 0;
+#endif
NOTE_LINE_NUMBER (note) = subtype;
BLOCK_FOR_INSN (note) = NULL;
@@ -4226,14 +3896,14 @@ emit_insn_after_1 (rtx first, rtx after)
rtx after_after;
basic_block bb;
- if (GET_CODE (after) != BARRIER
+ if (!BARRIER_P (after)
&& (bb = BLOCK_FOR_INSN (after)))
{
bb->flags |= BB_DIRTY;
for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
- if (GET_CODE (last) != BARRIER)
+ if (!BARRIER_P (last))
set_block_for_insn (last, bb);
- if (GET_CODE (last) != BARRIER)
+ if (!BARRIER_P (last))
set_block_for_insn (last, bb);
if (BB_END (bb) == after)
BB_END (bb) = last;
@@ -4262,10 +3932,7 @@ emit_insn_after_noloc (rtx x, rtx after)
{
rtx last = after;
-#ifdef ENABLE_RTL_CHECKING
- if (after == NULL_RTX)
- abort ();
-#endif
+ gcc_assert (after);
if (x == NULL_RTX)
return last;
@@ -4283,7 +3950,7 @@ emit_insn_after_noloc (rtx x, rtx after)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4321,10 +3988,7 @@ emit_jump_insn_after_noloc (rtx x, rtx after)
{
rtx last;
-#ifdef ENABLE_RTL_CHECKING
- if (after == NULL_RTX)
- abort ();
-#endif
+ gcc_assert (after);
switch (GET_CODE (x))
{
@@ -4339,7 +4003,7 @@ emit_jump_insn_after_noloc (rtx x, rtx after)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4360,10 +4024,7 @@ emit_call_insn_after_noloc (rtx x, rtx after)
{
rtx last;
-#ifdef ENABLE_RTL_CHECKING
- if (after == NULL_RTX)
- abort ();
-#endif
+ gcc_assert (after);
switch (GET_CODE (x))
{
@@ -4378,7 +4039,7 @@ emit_call_insn_after_noloc (rtx x, rtx after)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4429,7 +4090,9 @@ emit_note_after (int subtype, rtx after)
{
rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
+#ifndef USE_MAPPED_LOCATION
NOTE_SOURCE_FILE (note) = 0;
+#endif
NOTE_LINE_NUMBER (note) = subtype;
BLOCK_FOR_INSN (note) = NULL;
add_insn_after (note, after);
@@ -4682,7 +4345,7 @@ emit_insn (rtx x)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4723,7 +4386,7 @@ emit_jump_insn (rtx x)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4757,7 +4420,7 @@ emit_call_insn (rtx x)
#ifdef ENABLE_RTL_CHECKING
case SEQUENCE:
- abort ();
+ gcc_unreachable ();
break;
#endif
@@ -4807,12 +4470,15 @@ emit_line_note (location_t location)
{
rtx note;
- set_file_and_line_for_stmt (location);
-
+#ifdef USE_MAPPED_LOCATION
+ if (location == last_location)
+ return NULL_RTX;
+#else
if (location.file && last_location.file
&& !strcmp (location.file, last_location.file)
&& location.line == last_location.line)
return NULL_RTX;
+#endif
last_location = location;
if (no_line_numbers)
@@ -4821,8 +4487,12 @@ emit_line_note (location_t location)
return NULL_RTX;
}
+#ifdef USE_MAPPED_LOCATION
+ note = emit_note ((int) location);
+#else
note = emit_note (location.line);
NOTE_SOURCE_FILE (note) = location.file;
+#endif
return note;
}
@@ -4874,7 +4544,11 @@ emit_note (int note_no)
void
force_next_line_note (void)
{
+#ifdef USE_MAPPED_LOCATION
+ last_location = -1;
+#else
last_location.line = -1;
+#endif
}
/* Place a note of KIND on insn INSN with DATUM as the datum. If a
@@ -4895,8 +4569,7 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum)
means the insn only has one * useful * set). */
if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn))
{
- if (note)
- abort ();
+ gcc_assert (!note);
return NULL_RTX;
}
@@ -4923,10 +4596,10 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum)
/* Return an indication of which type of insn should have X as a body.
The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */
-enum rtx_code
+static enum rtx_code
classify_insn (rtx x)
{
- if (GET_CODE (x) == CODE_LABEL)
+ if (LABEL_P (x))
return CODE_LABEL;
if (GET_CODE (x) == CALL)
return CALL_INSN;
@@ -4965,33 +4638,35 @@ emit (rtx x)
{
enum rtx_code code = classify_insn (x);
- if (code == CODE_LABEL)
- return emit_label (x);
- else if (code == INSN)
- return emit_insn (x);
- else if (code == JUMP_INSN)
+ switch (code)
{
- rtx insn = emit_jump_insn (x);
- if (any_uncondjump_p (insn) || GET_CODE (x) == RETURN)
- return emit_barrier ();
- return insn;
+ case CODE_LABEL:
+ return emit_label (x);
+ case INSN:
+ return emit_insn (x);
+ case JUMP_INSN:
+ {
+ rtx insn = emit_jump_insn (x);
+ if (any_uncondjump_p (insn) || GET_CODE (x) == RETURN)
+ return emit_barrier ();
+ return insn;
+ }
+ case CALL_INSN:
+ return emit_call_insn (x);
+ default:
+ gcc_unreachable ();
}
- else if (code == CALL_INSN)
- return emit_call_insn (x);
- else
- abort ();
}
/* Space for free sequence stack entries. */
-static GTY ((deletable (""))) struct sequence_stack *free_sequence_stack;
+static GTY ((deletable)) struct sequence_stack *free_sequence_stack;
-/* Begin emitting insns to a sequence which can be packaged in an
- RTL_EXPR. If this sequence will contain something that might cause
- the compiler to pop arguments to function calls (because those
- pops have previously been deferred; see INHIBIT_DEFER_POP for more
- details), use do_pending_stack_adjust before calling this function.
- That will ensure that the deferred pops are not accidentally
- emitted in the middle of this sequence. */
+/* Begin emitting insns to a sequence. If this sequence will contain
+ something that might cause the compiler to pop arguments to function
+ calls (because those pops have previously been deferred; see
+ INHIBIT_DEFER_POP for more details), use do_pending_stack_adjust
+ before calling this function. That will ensure that the deferred
+ pops are not accidentally emitted in the middle of this sequence. */
void
start_sequence (void)
@@ -5009,7 +4684,6 @@ start_sequence (void)
tem->next = seq_stack;
tem->first = first_insn;
tem->last = last_insn;
- tem->sequence_rtl_expr = seq_rtl_expr;
seq_stack = tem;
@@ -5017,18 +4691,6 @@ start_sequence (void)
last_insn = 0;
}
-/* Similarly, but indicate that this sequence will be placed in T, an
- RTL_EXPR. See the documentation for start_sequence for more
- information about how to use this function. */
-
-void
-start_sequence_for_rtl_expr (tree t)
-{
- start_sequence ();
-
- seq_rtl_expr = t;
-}
-
/* Set up the insn chain starting with FIRST as the current sequence,
saving the previously current one. See the documentation for
start_sequence for more information about how to use this function. */
@@ -5046,19 +4708,6 @@ push_to_sequence (rtx first)
last_insn = last;
}
-/* Set up the insn chain from a chain stort in FIRST to LAST. */
-
-void
-push_to_full_sequence (rtx first, rtx last)
-{
- start_sequence ();
- first_insn = first;
- last_insn = last;
- /* We really should have the end of the insn chain here. */
- if (last && NEXT_INSN (last))
- abort ();
-}
-
/* Set up the outer-level insn chain
as the current sequence, saving the previously current one. */
@@ -5074,7 +4723,6 @@ push_topmost_sequence (void)
first_insn = top->first;
last_insn = top->last;
- seq_rtl_expr = top->sequence_rtl_expr;
}
/* After emitting to the outer-level insn chain, update the outer-level
@@ -5090,7 +4738,6 @@ pop_topmost_sequence (void)
top->first = first_insn;
top->last = last_insn;
- /* ??? Why don't we save seq_rtl_expr here? */
end_sequence ();
}
@@ -5115,7 +4762,6 @@ end_sequence (void)
first_insn = tem->first;
last_insn = tem->last;
- seq_rtl_expr = tem->sequence_rtl_expr;
seq_stack = tem->next;
memset (tem, 0, sizeof (*tem));
@@ -5123,17 +4769,6 @@ end_sequence (void)
free_sequence_stack = tem;
}
-/* This works like end_sequence, but records the old sequence in FIRST
- and LAST. */
-
-void
-end_full_sequence (rtx *first, rtx *last)
-{
- *first = first_insn;
- *last = last_insn;
- end_sequence ();
-}
-
/* Return 1 if currently emitting into a sequence. */
int
@@ -5144,7 +4779,7 @@ in_sequence_p (void)
/* Put the various virtual registers into REGNO_REG_RTX. */
-void
+static void
init_virtual_regs (struct emit_status *es)
{
rtx *ptr = es->x_regno_reg_rtx;
@@ -5196,7 +4831,6 @@ copy_insn_1 (rtx orig)
switch (code)
{
case REG:
- case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
case CONST_VECTOR:
@@ -5204,8 +4838,11 @@ copy_insn_1 (rtx orig)
case CODE_LABEL:
case PC:
case CC0:
- case ADDRESSOF:
return orig;
+ case CLOBBER:
+ if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER)
+ return orig;
+ break;
case SCRATCH:
for (i = 0; i < copy_insn_n_scratches; i++)
@@ -5231,20 +4868,18 @@ copy_insn_1 (rtx orig)
break;
}
- copy = rtx_alloc (code);
-
- /* Copy the various flags, and other information. We assume that
- all fields need copying, and then clear the fields that should
+ /* Copy the various flags, fields, and other information. We assume
+ that all fields need copying, and then clear the fields that should
not be copied. That is the sensible default behavior, and forces
us to explicitly document why we are *not* copying a flag. */
- memcpy (copy, orig, RTX_HDR_SIZE);
+ copy = shallow_copy_rtx (orig);
/* We do not copy the USED flag, which is used as a mark bit during
walks over the RTL. */
RTX_FLAG (copy, used) = 0;
/* We do not copy JUMP, CALL, or FRAME_RELATED for INSNs. */
- if (GET_RTX_CLASS (code) == 'i')
+ if (INSN_P (orig))
{
RTX_FLAG (copy, jump) = 0;
RTX_FLAG (copy, call) = 0;
@@ -5254,49 +4889,45 @@ copy_insn_1 (rtx orig)
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
- {
- copy->u.fld[i] = orig->u.fld[i];
- switch (*format_ptr++)
- {
- case 'e':
- if (XEXP (orig, i) != NULL)
- XEXP (copy, i) = copy_insn_1 (XEXP (orig, i));
- break;
+ switch (*format_ptr++)
+ {
+ case 'e':
+ if (XEXP (orig, i) != NULL)
+ XEXP (copy, i) = copy_insn_1 (XEXP (orig, i));
+ break;
- case 'E':
- case 'V':
- if (XVEC (orig, i) == orig_asm_constraints_vector)
- XVEC (copy, i) = copy_asm_constraints_vector;
- else if (XVEC (orig, i) == orig_asm_operands_vector)
- XVEC (copy, i) = copy_asm_operands_vector;
- else if (XVEC (orig, i) != NULL)
- {
- XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
- for (j = 0; j < XVECLEN (copy, i); j++)
- XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j));
- }
- break;
+ case 'E':
+ case 'V':
+ if (XVEC (orig, i) == orig_asm_constraints_vector)
+ XVEC (copy, i) = copy_asm_constraints_vector;
+ else if (XVEC (orig, i) == orig_asm_operands_vector)
+ XVEC (copy, i) = copy_asm_operands_vector;
+ else if (XVEC (orig, i) != NULL)
+ {
+ XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
+ for (j = 0; j < XVECLEN (copy, i); j++)
+ XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j));
+ }
+ break;
- case 't':
- case 'w':
- case 'i':
- case 's':
- case 'S':
- case 'u':
- case '0':
- /* These are left unchanged. */
- break;
+ case 't':
+ case 'w':
+ case 'i':
+ case 's':
+ case 'S':
+ case 'u':
+ case '0':
+ /* These are left unchanged. */
+ break;
- default:
- abort ();
- }
- }
+ default:
+ gcc_unreachable ();
+ }
if (code == SCRATCH)
{
i = copy_insn_n_scratches++;
- if (i >= MAX_RECOG_OPERANDS)
- abort ();
+ gcc_assert (i < MAX_RECOG_OPERANDS);
copy_insn_scratch_in[i] = orig;
copy_insn_scratch_out[i] = copy;
}
@@ -5338,13 +4969,10 @@ init_emit (void)
f->emit = ggc_alloc (sizeof (struct emit_status));
first_insn = NULL;
last_insn = NULL;
- seq_rtl_expr = NULL;
cur_insn_uid = 1;
reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
- last_location.line = 0;
- last_location.file = 0;
+ last_location = UNKNOWN_LOCATION;
first_label_num = label_num;
- last_label_num = 0;
seq_stack = NULL;
/* Init the tables that describe all the pseudo regs. */
@@ -5397,10 +5025,10 @@ init_emit (void)
#endif
}
-/* Generate the constant 0. */
+/* Generate a vector constant for mode MODE and constant value CONSTANT. */
static rtx
-gen_const_vector_0 (enum machine_mode mode)
+gen_const_vector (enum machine_mode mode, int constant)
{
rtx tem;
rtvec v;
@@ -5410,31 +5038,48 @@ gen_const_vector_0 (enum machine_mode mode)
units = GET_MODE_NUNITS (mode);
inner = GET_MODE_INNER (mode);
+ gcc_assert (!DECIMAL_FLOAT_MODE_P (inner));
+
v = rtvec_alloc (units);
- /* We need to call this function after we to set CONST0_RTX first. */
- if (!CONST0_RTX (inner))
- abort ();
+ /* We need to call this function after we set the scalar const_tiny_rtx
+ entries. */
+ gcc_assert (const_tiny_rtx[constant][(int) inner]);
for (i = 0; i < units; ++i)
- RTVEC_ELT (v, i) = CONST0_RTX (inner);
+ RTVEC_ELT (v, i) = const_tiny_rtx[constant][(int) inner];
tem = gen_rtx_raw_CONST_VECTOR (mode, v);
return tem;
}
/* Generate a vector like gen_rtx_raw_CONST_VEC, but use the zero vector when
- all elements are zero. */
+ all elements are zero, and the one vector when all elements are one. */
rtx
gen_rtx_CONST_VECTOR (enum machine_mode mode, rtvec v)
{
- rtx inner_zero = CONST0_RTX (GET_MODE_INNER (mode));
+ enum machine_mode inner = GET_MODE_INNER (mode);
+ int nunits = GET_MODE_NUNITS (mode);
+ rtx x;
int i;
- for (i = GET_MODE_NUNITS (mode) - 1; i >= 0; i--)
- if (RTVEC_ELT (v, i) != inner_zero)
- return gen_rtx_raw_CONST_VECTOR (mode, v);
- return CONST0_RTX (mode);
+ /* Check to see if all of the elements have the same value. */
+ x = RTVEC_ELT (v, nunits - 1);
+ for (i = nunits - 2; i >= 0; i--)
+ if (RTVEC_ELT (v, i) != x)
+ break;
+
+ /* If the values are all the same, check to see if we can use one of the
+ standard constant vectors. */
+ if (i == -1)
+ {
+ if (x == CONST0_RTX (inner))
+ return CONST0_RTX (mode);
+ else if (x == CONST1_RTX (inner))
+ return CONST1_RTX (mode);
+ }
+
+ return gen_rtx_raw_CONST_VECTOR (mode, v);
}
/* Create some permanent unique rtl objects shared between all functions.
@@ -5471,7 +5116,8 @@ init_emit_once (int line_numbers)
word_mode = VOIDmode;
double_mode = VOIDmode;
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
@@ -5483,7 +5129,8 @@ init_emit_once (int line_numbers)
word_mode = mode;
}
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+ mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
if (GET_MODE_BITSIZE (mode) == DOUBLE_TYPE_SIZE
@@ -5497,8 +5144,8 @@ init_emit_once (int line_numbers)
This must be done at runtime because the register number field
is in a union and some compilers can't initialize unions. */
- pc_rtx = gen_rtx (PC, VOIDmode);
- cc0_rtx = gen_rtx (CC0, VOIDmode);
+ pc_rtx = gen_rtx_PC (VOIDmode);
+ cc0_rtx = gen_rtx_CC0 (VOIDmode);
stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
if (hard_frame_pointer_rtx == 0)
@@ -5531,7 +5178,7 @@ init_emit_once (int line_numbers)
/* Create the unique rtx's for certain rtx codes and operand values. */
- /* Don't use gen_rtx here since gen_rtx in this case
+ /* Don't use gen_rtx_CONST_INT here since gen_rtx_CONST_INT in this case
tries to use these variables. */
for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++)
const_int_rtx[i + MAX_SAVED_CONST_INT] =
@@ -5552,7 +5199,7 @@ init_emit_once (int line_numbers)
REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode);
dconsthalf = dconst1;
- dconsthalf.exp--;
+ SET_REAL_EXP (&dconsthalf, REAL_EXP (&dconsthalf) - 1);
real_arithmetic (&dconstthird, RDIV_EXPR, &dconst1, &dconst3);
@@ -5568,14 +5215,22 @@ init_emit_once (int line_numbers)
REAL_VALUE_TYPE *r =
(i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ const_tiny_rtx[i][(int) mode] =
+ CONST_DOUBLE_FROM_REAL_VALUE (*r, mode);
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_DECIMAL_FLOAT);
+ mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
const_tiny_rtx[i][(int) mode] =
CONST_DOUBLE_FROM_REAL_VALUE (*r, mode);
const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i);
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
const_tiny_rtx[i][(int) mode] = GEN_INT (i);
@@ -5588,12 +5243,18 @@ init_emit_once (int line_numbers)
for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- const_tiny_rtx[0][(int) mode] = gen_const_vector_0 (mode);
+ {
+ const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
+ const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
+ }
for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- const_tiny_rtx[0][(int) mode] = gen_const_vector_0 (mode);
+ {
+ const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
+ const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
+ }
for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i)
if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC)
@@ -5634,27 +5295,6 @@ init_emit_once (int line_numbers)
pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
}
-/* Query and clear/ restore no_line_numbers. This is used by the
- switch / case handling in stmt.c to give proper line numbers in
- warnings about unreachable code. */
-
-int
-force_line_numbers (void)
-{
- int old = no_line_numbers;
-
- no_line_numbers = 0;
- if (old)
- force_next_line_note ();
- return old;
-}
-
-void
-restore_line_number_status (int old_value)
-{
- no_line_numbers = old_value;
-}
-
/* Produce exact duplicate of insn INSN after AFTER.
Care updating of libcall regions if present. */
@@ -5684,7 +5324,7 @@ emit_copy_of_insn_after (rtx insn, rtx after)
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Update LABEL_NUSES. */
@@ -5692,6 +5332,11 @@ emit_copy_of_insn_after (rtx insn, rtx after)
INSN_LOCATOR (new) = INSN_LOCATOR (insn);
+ /* If the old insn is frame related, then so is the new one. This is
+ primarily needed for IA-64 unwind info which marks epilogue insns,
+ which may be duplicated by the basic block reordering code. */
+ RTX_FRAME_RELATED_P (new) = RTX_FRAME_RELATED_P (insn);
+
/* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
make them. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
@@ -5722,4 +5367,15 @@ emit_copy_of_insn_after (rtx insn, rtx after)
return new;
}
+static GTY((deletable)) rtx hard_reg_clobbers [NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+rtx
+gen_hard_reg_clobber (enum machine_mode mode, unsigned int regno)
+{
+ if (hard_reg_clobbers[mode][regno])
+ return hard_reg_clobbers[mode][regno];
+ else
+ return (hard_reg_clobbers[mode][regno] =
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
+}
+
#include "gt-emit-rtl.h"
diff --git a/contrib/gcc/final.c b/contrib/gcc/final.c
index dd5b64e..d64f0c3 100644
--- a/contrib/gcc/final.c
+++ b/contrib/gcc/final.c
@@ -1,6 +1,7 @@
/* Convert RTL to assembler code and output it, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* This is the final pass of the compiler.
It looks at the rtl code for a function and outputs assembler code.
@@ -71,6 +72,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "debug.h"
#include "expr.h"
#include "cfglayout.h"
+#include "tree-pass.h"
+#include "timevar.h"
+#include "cgraph.h"
+#include "coverage.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@@ -85,6 +90,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "dbxout.h"
#endif
+#ifdef SDB_DEBUGGING_INFO
+#include "sdbout.h"
+#endif
+
/* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a
null default for it to save conditionalization later. */
#ifndef CC_STATUS_INIT
@@ -105,12 +114,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define JUMP_TABLES_IN_TEXT_SECTION 0
#endif
-#if defined(READONLY_DATA_SECTION) || defined(READONLY_DATA_SECTION_ASM_OP)
-#define HAVE_READONLY_DATA_SECTION 1
-#else
-#define HAVE_READONLY_DATA_SECTION 0
-#endif
-
/* Bitflags used by final_scan_insn. */
#define SEEN_BB 1
#define SEEN_NOTE 2
@@ -132,10 +135,13 @@ static int high_function_linenum;
/* Filename of last NOTE. */
static const char *last_filename;
-extern int length_unit_log; /* This is defined in insn-attrtab.c. */
+/* Whether to force emission of a line note before the next insn. */
+static bool force_source_line = false;
+
+extern const int length_unit_log; /* This is defined in insn-attrtab.c. */
/* Nonzero while outputting an `asm' with operands.
- This means that inconsistencies are the user's fault, so don't abort.
+ This means that inconsistencies are the user's fault, so don't die.
The precise value is the insn being output, to pass to error_for_asm. */
rtx this_is_asm_operands;
@@ -374,10 +380,11 @@ init_insn_lengths (void)
}
/* Obtain the current length of an insn. If branch shortening has been done,
- get its actual length. Otherwise, get its maximum length. */
-
-int
-get_attr_length (rtx insn ATTRIBUTE_UNUSED)
+ get its actual length. Otherwise, use FALLBACK_FN to calculate the
+ length. */
+static inline int
+get_attr_length_1 (rtx insn ATTRIBUTE_UNUSED,
+ int (*fallback_fn) (rtx) ATTRIBUTE_UNUSED)
{
#ifdef HAVE_ATTR_length
rtx body;
@@ -395,7 +402,7 @@ get_attr_length (rtx insn ATTRIBUTE_UNUSED)
return 0;
case CALL_INSN:
- length = insn_default_length (insn);
+ length = fallback_fn (insn);
break;
case JUMP_INSN:
@@ -406,7 +413,7 @@ get_attr_length (rtx insn ATTRIBUTE_UNUSED)
ADDR_VEC_ALIGN. */
}
else
- length = insn_default_length (insn);
+ length = fallback_fn (insn);
break;
case INSN:
@@ -415,12 +422,12 @@ get_attr_length (rtx insn ATTRIBUTE_UNUSED)
return 0;
else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
- length = asm_insn_count (body) * insn_default_length (insn);
+ length = asm_insn_count (body) * fallback_fn (insn);
else if (GET_CODE (body) == SEQUENCE)
for (i = 0; i < XVECLEN (body, 0); i++)
length += get_attr_length (XVECEXP (body, 0, i));
else
- length = insn_default_length (insn);
+ length = fallback_fn (insn);
break;
default:
@@ -433,8 +440,26 @@ get_attr_length (rtx insn ATTRIBUTE_UNUSED)
return length;
#else /* not HAVE_ATTR_length */
return 0;
+#define insn_default_length 0
+#define insn_min_length 0
#endif /* not HAVE_ATTR_length */
}
+
+/* Obtain the current length of an insn. If branch shortening has been done,
+ get its actual length. Otherwise, get its maximum length. */
+int
+get_attr_length (rtx insn)
+{
+ return get_attr_length_1 (insn, insn_default_length);
+}
+
+/* Obtain the current length of an insn. If branch shortening has been done,
+ get its actual length. Otherwise, get its minimum length. */
+int
+get_attr_min_length (rtx insn)
+{
+ return get_attr_length_1 (insn, insn_min_length);
+}
/* Code to handle alignment inside shorten_branches. */
@@ -625,7 +650,7 @@ insn_current_reference_address (rtx branch)
seq = NEXT_INSN (PREV_INSN (branch));
seq_uid = INSN_UID (seq);
- if (GET_CODE (branch) != JUMP_INSN)
+ if (!JUMP_P (branch))
/* This can happen for example on the PA; the objective is to know the
offset to address something in front of the start of the function.
Thus, we can treat it like a backward branch.
@@ -651,7 +676,10 @@ insn_current_reference_address (rtx branch)
}
#endif /* HAVE_ATTR_length */
-void
+/* Compute branch alignments based on frequency information in the
+ CFG. */
+
+static unsigned int
compute_alignments (void)
{
int log, max_skip, max_log;
@@ -665,26 +693,26 @@ compute_alignments (void)
max_labelno = max_label_num ();
min_labelno = get_first_label_num ();
- label_align = xcalloc (max_labelno - min_labelno + 1,
- sizeof (struct label_alignment));
+ label_align = XCNEWVEC (struct label_alignment, max_labelno - min_labelno + 1);
/* If not optimizing or optimizing for size, don't assign any alignments. */
if (! optimize || optimize_size)
- return;
+ return 0;
FOR_EACH_BB (bb)
{
rtx label = BB_HEAD (bb);
int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
edge e;
+ edge_iterator ei;
- if (GET_CODE (label) != CODE_LABEL
+ if (!LABEL_P (label)
|| probably_never_executed_bb_p (bb))
continue;
max_log = LABEL_ALIGN (label);
max_skip = LABEL_ALIGN_MAX_SKIP;
- for (e = bb->pred; e; e = e->pred_next)
+ FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->flags & EDGE_FALLTHRU)
has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e);
@@ -732,7 +760,26 @@ compute_alignments (void)
LABEL_TO_ALIGNMENT (label) = max_log;
LABEL_TO_MAX_SKIP (label) = max_skip;
}
+ return 0;
}
+
+struct tree_opt_pass pass_compute_alignments =
+{
+ NULL, /* name */
+ NULL, /* gate */
+ compute_alignments, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+ 0 /* letter */
+};
+
/* Make a pass over all insns and compute their actual lengths by shortening
any branches of variable length if possible. */
@@ -767,7 +814,10 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
/* Compute maximum UID and allocate label_align / uid_shuid. */
max_uid = get_max_uid ();
- uid_shuid = xmalloc (max_uid * sizeof *uid_shuid);
+ /* Free uid_shuid before reallocating it. */
+ free (uid_shuid);
+
+ uid_shuid = XNEWVEC (int, max_uid);
if (max_labelno != max_label_num ())
{
@@ -783,10 +833,9 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
label_align = xrealloc (label_align,
n_labels * sizeof (struct label_alignment));
- /* Range of labels grows monotonically in the function. Abort here
+ /* Range of labels grows monotonically in the function. Failing here
means that the initialization of array got lost. */
- if (n_old_labels > n_labels)
- abort ();
+ gcc_assert (n_old_labels <= n_labels);
memset (label_align + n_old_labels, 0,
(n_labels - n_old_labels) * sizeof (struct label_alignment));
@@ -807,14 +856,9 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
INSN_SHUID (insn) = i++;
if (INSN_P (insn))
- {
- /* reorg might make the first insn of a loop being run once only,
- and delete the label in front of it. Then we want to apply
- the loop alignment to the new label created by reorg, which
- is separated by the former loop start insn from the
- NOTE_INSN_LOOP_BEG. */
- }
- else if (GET_CODE (insn) == CODE_LABEL)
+ continue;
+
+ if (LABEL_P (insn))
{
rtx next;
@@ -832,11 +876,12 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
max_log = log;
max_skip = LABEL_ALIGN_MAX_SKIP;
}
- next = NEXT_INSN (insn);
+ next = next_nonnote_insn (insn);
/* ADDR_VECs only take room if read-only data goes into the text
section. */
- if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
- if (next && GET_CODE (next) == JUMP_INSN)
+ if (JUMP_TABLES_IN_TEXT_SECTION
+ || readonly_data_section == text_section)
+ if (next && JUMP_P (next))
{
rtx nextbody = PATTERN (next);
if (GET_CODE (nextbody) == ADDR_VEC
@@ -855,13 +900,13 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
max_log = 0;
max_skip = 0;
}
- else if (GET_CODE (insn) == BARRIER)
+ else if (BARRIER_P (insn))
{
rtx label;
for (label = insn; label && ! INSN_P (label);
label = NEXT_INSN (label))
- if (GET_CODE (label) == CODE_LABEL)
+ if (LABEL_P (label))
{
log = LABEL_ALIGN_AFTER_BARRIER (insn);
if (max_log < log)
@@ -876,20 +921,20 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
#ifdef HAVE_ATTR_length
/* Allocate the rest of the arrays. */
- insn_lengths = xmalloc (max_uid * sizeof (*insn_lengths));
+ insn_lengths = XNEWVEC (int, max_uid);
insn_lengths_max_uid = max_uid;
/* Syntax errors can lead to labels being outside of the main insn stream.
Initialize insn_addresses, so that we get reproducible results. */
INSN_ADDRESSES_ALLOC (max_uid);
- varying_length = xcalloc (max_uid, sizeof (char));
+ varying_length = XCNEWVEC (char, max_uid);
/* Initialize uid_align. We scan instructions
from end to start, and keep in align_tab[n] the last seen insn
that does an alignment of at least n+1, i.e. the successor
in the alignment chain for an insn that does / has a known
alignment of n. */
- uid_align = xcalloc (max_uid, sizeof *uid_align);
+ uid_align = XCNEWVEC (rtx, max_uid);
for (i = MAX_CODE_ALIGN; --i >= 0;)
align_tab[i] = NULL_RTX;
@@ -898,7 +943,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
{
int uid = INSN_UID (seq);
int log;
- log = (GET_CODE (seq) == CODE_LABEL ? LABEL_TO_ALIGNMENT (seq) : 0);
+ log = (LABEL_P (seq) ? LABEL_TO_ALIGNMENT (seq) : 0);
uid_align[uid] = align_tab[0];
if (log)
{
@@ -925,13 +970,12 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
int min_align;
addr_diff_vec_flags flags;
- if (GET_CODE (insn) != JUMP_INSN
+ if (!JUMP_P (insn)
|| GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
continue;
pat = PATTERN (insn);
len = XVECLEN (pat, 1);
- if (len <= 0)
- abort ();
+ gcc_assert (len > 0);
min_align = MAX_CODE_ALIGN;
for (min = max_shuid, max = min_shuid, i = len - 1; i >= 0; i--)
{
@@ -950,10 +994,11 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
if (min_align > LABEL_TO_ALIGNMENT (lab))
min_align = LABEL_TO_ALIGNMENT (lab);
}
- XEXP (pat, 2) = gen_rtx_LABEL_REF (VOIDmode, min_lab);
- XEXP (pat, 3) = gen_rtx_LABEL_REF (VOIDmode, max_lab);
+ XEXP (pat, 2) = gen_rtx_LABEL_REF (Pmode, min_lab);
+ XEXP (pat, 3) = gen_rtx_LABEL_REF (Pmode, max_lab);
insn_shuid = INSN_SHUID (insn);
rel = INSN_SHUID (XEXP (XEXP (pat, 0), 0));
+ memset (&flags, 0, sizeof (flags));
flags.min_align = min_align;
flags.base_after_vec = rel > insn_shuid;
flags.min_after_vec = min > insn_shuid;
@@ -974,7 +1019,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
insn_lengths[uid] = 0;
- if (GET_CODE (insn) == CODE_LABEL)
+ if (LABEL_P (insn))
{
int log = LABEL_TO_ALIGNMENT (insn);
if (log)
@@ -987,8 +1032,8 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
- if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
- || GET_CODE (insn) == CODE_LABEL)
+ if (NOTE_P (insn) || BARRIER_P (insn)
+ || LABEL_P (insn))
continue;
if (INSN_DELETED_P (insn))
continue;
@@ -998,7 +1043,8 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
{
/* This only takes room if read-only data goes into the text
section. */
- if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
+ if (JUMP_TABLES_IN_TEXT_SECTION
+ || readonly_data_section == text_section)
insn_lengths[uid] = (XVECLEN (body,
GET_CODE (body) == ADDR_DIFF_VEC)
* GET_MODE_SIZE (GET_MODE (body)));
@@ -1079,7 +1125,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
uid = INSN_UID (insn);
- if (GET_CODE (insn) == CODE_LABEL)
+ if (LABEL_P (insn))
{
int log = LABEL_TO_ALIGNMENT (insn);
if (log > insn_current_align)
@@ -1104,7 +1150,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
INSN_ADDRESSES (uid) = insn_current_address;
#ifdef CASE_VECTOR_SHORTEN_MODE
- if (optimize && GET_CODE (insn) == JUMP_INSN
+ if (optimize && JUMP_P (insn)
&& GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
{
rtx body = PATTERN (insn);
@@ -1199,7 +1245,8 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
max_addr - rel_addr,
body));
- if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
+ if (JUMP_TABLES_IN_TEXT_SECTION
+ || readonly_data_section == text_section)
{
insn_lengths[uid]
= (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
@@ -1214,7 +1261,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
if (! (varying_length[uid]))
{
- if (GET_CODE (insn) == INSN
+ if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
{
int i;
@@ -1236,7 +1283,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
continue;
}
- if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
{
int i;
@@ -1344,7 +1391,7 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
(*debug_hooks->begin_prologue) (last_linenum, last_filename);
-#if defined (DWARF2_UNWIND_INFO) || defined (IA64_UNWIND_INFO)
+#if defined (DWARF2_UNWIND_INFO) || defined (TARGET_UNWIND_INFO)
if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG)
dwarf2out_begin_prologue (0, NULL);
#endif
@@ -1363,14 +1410,13 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
if (dwarf2out_do_frame ())
- dwarf2out_frame_debug (NULL_RTX);
+ dwarf2out_frame_debug (NULL_RTX, false);
#endif
/* If debugging, assign block numbers to all of the blocks in this
function. */
if (write_symbols)
{
- remove_unnecessary_notes ();
reemit_insn_block_notes ();
number_blocks (current_function_decl);
/* We never actually put out begin/end notes for the top-level
@@ -1380,7 +1426,7 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
}
/* First output the function prologue: code to set up the stack frame. */
- (*targetm.asm_out.function_prologue) (file, get_frame_size ());
+ targetm.asm_out.function_prologue (file, get_frame_size ());
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
@@ -1409,23 +1455,23 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
int sval = current_function_returns_struct;
rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1);
#if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM)
- int cxt = current_function_needs_context;
+ int cxt = cfun->static_chain_decl != NULL;
#endif
#endif /* ASM_OUTPUT_REG_PUSH */
if (! NO_PROFILE_COUNTERS)
{
int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
- data_section ();
+ switch_to_section (data_section);
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
- (*targetm.asm_out.internal_label) (file, "LP", current_function_funcdef_no);
+ targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no);
assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
}
- function_section (current_function_decl);
+ switch_to_section (current_function_section ());
#if defined(ASM_OUTPUT_REG_PUSH)
- if (sval && svrtx != NULL_RTX && GET_CODE (svrtx) == REG)
+ if (sval && svrtx != NULL_RTX && REG_P (svrtx))
ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
#endif
@@ -1456,7 +1502,7 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
#endif
#if defined(ASM_OUTPUT_REG_PUSH)
- if (sval && svrtx != NULL_RTX && GET_CODE (svrtx) == REG)
+ if (sval && svrtx != NULL_RTX && REG_P (svrtx))
ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
#endif
}
@@ -1474,7 +1520,7 @@ final_end_function (void)
/* Finally, output the function epilogue:
code to restore the stack frame and return to the caller. */
- (*targetm.asm_out.function_epilogue) (asm_out_file, get_frame_size ());
+ targetm.asm_out.function_epilogue (asm_out_file, get_frame_size ());
/* And debug output. */
(*debug_hooks->end_epilogue) (last_linenum, last_filename);
@@ -1487,18 +1533,10 @@ final_end_function (void)
}
/* Output assembler code for some insns: all or part of a function.
- For description of args, see `final_start_function', above.
-
- PRESCAN is 1 if we are not really outputting,
- just scanning as if we were outputting.
- Prescanning deletes and rearranges insns just like ordinary output.
- PRESCAN is -2 if we are outputting after having prescanned.
- In this case, don't try to delete or rearrange insns
- because that has already been done.
- Prescanning is done only on certain machines. */
+ For description of args, see `final_start_function', above. */
void
-final (rtx first, FILE *file, int optimize, int prescan)
+final (rtx first, FILE *file, int optimize)
{
rtx insn;
int max_uid = 0;
@@ -1514,13 +1552,16 @@ final (rtx first, FILE *file, int optimize, int prescan)
{
rtx last = 0;
for (insn = first; insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
+ if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0)
{
- if ((RTX_INTEGRATED_P (insn)
- && strcmp (NOTE_SOURCE_FILE (insn), main_input_filename) != 0)
- || (last != 0
- && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)
- && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)))
+ if (last != 0
+#ifdef USE_MAPPED_LOCATION
+ && NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last)
+#else
+ && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)
+ && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)
+#endif
+ )
{
delete_insn (insn); /* Use delete_note. */
continue;
@@ -1537,7 +1578,7 @@ final (rtx first, FILE *file, int optimize, int prescan)
#ifdef HAVE_cc0
/* If CC tracking across branches is enabled, record the insn which
jumps to each branch only reached from one place. */
- if (optimize && GET_CODE (insn) == JUMP_INSN)
+ if (optimize && JUMP_P (insn))
{
rtx lab = JUMP_LABEL (insn);
if (lab && LABEL_NUSES (lab) == 1)
@@ -1560,16 +1601,14 @@ final (rtx first, FILE *file, int optimize, int prescan)
{
/* This can be triggered by bugs elsewhere in the compiler if
new insns are created after init_insn_lengths is called. */
- if (GET_CODE (insn) == NOTE)
- insn_current_address = -1;
- else
- abort ();
+ gcc_assert (NOTE_P (insn));
+ insn_current_address = -1;
}
else
insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
#endif /* HAVE_ATTR_length */
- insn = final_scan_insn (insn, file, optimize, prescan, 0, &seen);
+ insn = final_scan_insn (insn, file, optimize, 0, &seen);
}
}
@@ -1583,12 +1622,11 @@ get_insn_template (int code, rtx insn)
case INSN_OUTPUT_FORMAT_MULTI:
return insn_data[code].output.multi[which_alternative];
case INSN_OUTPUT_FORMAT_FUNCTION:
- if (insn == NULL)
- abort ();
+ gcc_assert (insn);
return (*insn_data[code].output.function) (recog_data.operand, insn);
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -1609,7 +1647,7 @@ output_alternate_entry_point (FILE *file, rtx insn)
ASM_WEAKEN_LABEL (file, name);
#endif
case LABEL_GLOBAL_ENTRY:
- (*targetm.asm_out.globalize_label) (file, name);
+ targetm.asm_out.globalize_label (file, name);
case LABEL_STATIC_ENTRY:
#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
@@ -1619,7 +1657,7 @@ output_alternate_entry_point (FILE *file, rtx insn)
case LABEL_NORMAL:
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -1639,12 +1677,12 @@ output_alternate_entry_point (FILE *file, rtx insn)
rtx
final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
- int prescan, int nopeepholes ATTRIBUTE_UNUSED,
- int *seen)
+ int nopeepholes ATTRIBUTE_UNUSED, int *seen)
{
#ifdef HAVE_cc0
rtx set;
#endif
+ rtx next;
insn_counter++;
@@ -1656,26 +1694,25 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
switch (GET_CODE (insn))
{
case NOTE:
- if (prescan > 0)
- break;
-
switch (NOTE_LINE_NUMBER (insn))
{
case NOTE_INSN_DELETED:
- case NOTE_INSN_LOOP_BEG:
- case NOTE_INSN_LOOP_END:
- case NOTE_INSN_LOOP_END_TOP_COND:
- case NOTE_INSN_LOOP_CONT:
- case NOTE_INSN_LOOP_VTOP:
case NOTE_INSN_FUNCTION_END:
case NOTE_INSN_REPEATED_LINE_NUMBER:
case NOTE_INSN_EXPECTED_VALUE:
break;
+ case NOTE_INSN_SWITCH_TEXT_SECTIONS:
+ in_cold_section_p = !in_cold_section_p;
+ (*debug_hooks->switch_text_section) ();
+ switch_to_section (current_function_section ());
+ break;
+
case NOTE_INSN_BASIC_BLOCK:
-#ifdef IA64_UNWIND_INFO
- IA64_UNWIND_EMIT (asm_out_file, insn);
+#ifdef TARGET_UNWIND_INFO
+ targetm.asm_out.unwind_emit (asm_out_file, insn);
#endif
+
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s basic block %d\n",
ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index);
@@ -1683,7 +1720,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB)
{
*seen |= SEEN_EMITTED;
- last_filename = NULL;
+ force_source_line = true;
}
else
*seen |= SEEN_BB;
@@ -1701,13 +1738,13 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
break;
case NOTE_INSN_PROLOGUE_END:
- (*targetm.asm_out.function_end_prologue) (file);
+ targetm.asm_out.function_end_prologue (file);
profile_after_prologue (file);
if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
{
*seen |= SEEN_EMITTED;
- last_filename = NULL;
+ force_source_line = true;
}
else
*seen |= SEEN_NOTE;
@@ -1715,7 +1752,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
break;
case NOTE_INSN_EPILOGUE_BEG:
- (*targetm.asm_out.function_begin_epilogue) (file);
+ targetm.asm_out.function_begin_epilogue (file);
break;
case NOTE_INSN_FUNCTION_BEG:
@@ -1725,7 +1762,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
{
*seen |= SEEN_EMITTED;
- last_filename = NULL;
+ force_source_line = true;
}
else
*seen |= SEEN_NOTE;
@@ -1735,7 +1772,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
case NOTE_INSN_BLOCK_BEG:
if (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
- || write_symbols == DWARF_DEBUG
|| write_symbols == DWARF2_DEBUG
|| write_symbols == VMS_AND_DWARF2_DEBUG
|| write_symbols == VMS_DEBUG)
@@ -1757,7 +1793,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
case NOTE_INSN_BLOCK_END:
if (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
- || write_symbols == DWARF_DEBUG
|| write_symbols == DWARF2_DEBUG
|| write_symbols == VMS_AND_DWARF2_DEBUG
|| write_symbols == VMS_DEBUG)
@@ -1768,8 +1803,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
/* End of a symbol-block. */
--block_depth;
- if (block_depth < 0)
- abort ();
+ gcc_assert (block_depth >= 0);
(*debug_hooks->end_block) (high_block_linenum, n);
}
@@ -1782,12 +1816,15 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
break;
+ case NOTE_INSN_VAR_LOCATION:
+ (*debug_hooks->var_location) (insn);
+ break;
+
case 0:
break;
default:
- if (NOTE_LINE_NUMBER (insn) <= 0)
- abort ();
+ gcc_assert (NOTE_LINE_NUMBER (insn) > 0);
break;
}
break;
@@ -1795,7 +1832,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
case BARRIER:
#if defined (DWARF2_UNWIND_INFO)
if (dwarf2out_do_frame ())
- dwarf2out_frame_debug (insn);
+ dwarf2out_frame_debug (insn, false);
#endif
break;
@@ -1839,18 +1876,16 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
insn, and that branch is the only way to reach this label,
set the condition codes based on the branch and its
predecessor. */
- if (barrier && GET_CODE (barrier) == BARRIER
- && jump && GET_CODE (jump) == JUMP_INSN
+ if (barrier && BARRIER_P (barrier)
+ && jump && JUMP_P (jump)
&& (prev = prev_nonnote_insn (jump))
- && GET_CODE (prev) == INSN)
+ && NONJUMP_INSN_P (prev))
{
NOTICE_UPDATE_CC (PATTERN (prev), prev);
NOTICE_UPDATE_CC (PATTERN (jump), jump);
}
}
#endif
- if (prescan > 0)
- break;
if (LABEL_NAME (insn))
(*debug_hooks->label) (insn);
@@ -1860,10 +1895,11 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
fputs (ASM_APP_OFF, file);
app_on = 0;
}
- if (NEXT_INSN (insn) != 0
- && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)
+
+ next = next_nonnote_insn (insn);
+ if (next != 0 && JUMP_P (next))
{
- rtx nextbody = PATTERN (NEXT_INSN (insn));
+ rtx nextbody = PATTERN (next);
/* If this label is followed by a jump-table,
make sure we put the label in the read-only section. Also
@@ -1881,23 +1917,24 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
{
int log_align;
- readonly_data_section ();
+ switch_to_section (targetm.asm_out.function_rodata_section
+ (current_function_decl));
#ifdef ADDR_VEC_ALIGN
- log_align = ADDR_VEC_ALIGN (NEXT_INSN (insn));
+ log_align = ADDR_VEC_ALIGN (next);
#else
log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
#endif
ASM_OUTPUT_ALIGN (file, log_align);
}
else
- function_section (current_function_decl);
+ switch_to_section (current_function_section ());
#ifdef ASM_OUTPUT_CASE_LABEL
ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
- NEXT_INSN (insn));
+ next);
#else
- (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (insn));
+ targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
#endif
#endif
break;
@@ -1906,7 +1943,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
if (LABEL_ALT_ENTRY_P (insn))
output_alternate_entry_point (file, insn);
else
- (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (insn));
+ targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
break;
default:
@@ -1914,8 +1951,11 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
rtx body = PATTERN (insn);
int insn_code_number;
const char *template;
- rtx note;
+#ifdef HAVE_conditional_execution
+ /* Reset this early so it is correct for ASM statements. */
+ current_insn_predicate = NULL_RTX;
+#endif
/* An INSN, JUMP_INSN or CALL_INSN.
First check for special kinds that recog doesn't recognize. */
@@ -1924,17 +1964,19 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
break;
#ifdef HAVE_cc0
- /* If there is a REG_CC_SETTER note on this insn, it means that
- the setting of the condition code was done in the delay slot
- of the insn that branched here. So recover the cc status
- from the insn that set it. */
+ {
+ /* If there is a REG_CC_SETTER note on this insn, it means that
+ the setting of the condition code was done in the delay slot
+ of the insn that branched here. So recover the cc status
+ from the insn that set it. */
- note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
- if (note)
- {
- NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
- cc_prev_status = cc_status;
- }
+ rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
+ if (note)
+ {
+ NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
+ cc_prev_status = cc_status;
+ }
+ }
#endif
/* Detect insns that are really jump-tables
@@ -1946,8 +1988,11 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
int vlen, idx;
#endif
- if (prescan > 0)
- break;
+ if (! JUMP_TABLES_IN_TEXT_SECTION)
+ switch_to_section (targetm.asm_out.function_rodata_section
+ (current_function_decl));
+ else
+ switch_to_section (current_function_section ());
if (app_on)
{
@@ -1961,7 +2006,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
#ifdef ASM_OUTPUT_ADDR_VEC
ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body);
#else
- abort ();
+ gcc_unreachable ();
#endif
}
else
@@ -1969,7 +2014,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
#ifdef ASM_OUTPUT_ADDR_DIFF_VEC
ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body);
#else
- abort ();
+ gcc_unreachable ();
#endif
}
#else
@@ -1982,7 +2027,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
ASM_OUTPUT_ADDR_VEC_ELT
(file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
#else
- abort ();
+ gcc_unreachable ();
#endif
}
else
@@ -1994,7 +2039,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
#else
- abort ();
+ gcc_unreachable ();
#endif
}
}
@@ -2005,7 +2050,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
#endif
#endif
- function_section (current_function_decl);
+ switch_to_section (current_function_section ());
break;
}
@@ -2022,8 +2067,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
/* There's no telling what that did to the condition codes. */
CC_STATUS_INIT;
- if (prescan > 0)
- break;
if (string[0])
{
@@ -2046,12 +2089,10 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
/* There's no telling what that did to the condition codes. */
CC_STATUS_INIT;
- if (prescan > 0)
- break;
/* Get out the operand values. */
string = decode_asm_operands (body, ops, NULL, NULL, NULL);
- /* Inhibit aborts on what would otherwise be compiler bugs. */
+ /* Inhibit dieing on what would otherwise be compiler bugs. */
insn_noperands = noperands;
this_is_asm_operands = insn;
@@ -2074,7 +2115,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
break;
}
- if (prescan <= 0 && app_on)
+ if (app_on)
{
fputs (ASM_APP_OFF, file);
app_on = 0;
@@ -2084,10 +2125,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
{
/* A delayed-branch sequence */
int i;
- rtx next;
- if (prescan > 0)
- break;
final_sequence = body;
/* Record the delay slots' frame information before the branch.
@@ -2095,7 +2133,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
#if defined (DWARF2_UNWIND_INFO)
if (dwarf2out_do_frame ())
for (i = 1; i < XVECLEN (body, 0); i++)
- dwarf2out_frame_debug (XVECEXP (body, 0, i));
+ dwarf2out_frame_debug (XVECEXP (body, 0, i), false);
#endif
/* The first insn in this SEQUENCE might be a JUMP_INSN that will
@@ -2103,7 +2141,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
thought unnecessary. If that happens, cancel this sequence
and cause that insn to be restored. */
- next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1, seen);
+ next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, 1, seen);
if (next != XVECEXP (body, 0, 1))
{
final_sequence = 0;
@@ -2117,7 +2155,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
/* We loop in case any instruction in a delay slot gets
split. */
do
- insn = final_scan_insn (insn, file, 0, prescan, 1, seen);
+ insn = final_scan_insn (insn, file, 0, 1, seen);
while (insn != next);
}
#ifdef DBR_OUTPUT_SEQEND
@@ -2130,7 +2168,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
called function. Hence we don't preserve any CC-setting
actions in these insns and the CC must be marked as being
clobbered by the function. */
- if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN)
+ if (CALL_P (XVECEXP (body, 0, 0)))
{
CC_STATUS_INIT;
}
@@ -2188,20 +2226,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
}
#endif
-#ifndef STACK_REGS
- /* Don't bother outputting obvious no-ops, even without -O.
- This optimization is fast and doesn't interfere with debugging.
- Don't do this if the insn is in a delay slot, since this
- will cause an improper number of delay insns to be written. */
- if (final_sequence == 0
- && prescan >= 0
- && GET_CODE (insn) == INSN && GET_CODE (body) == SET
- && GET_CODE (SET_SRC (body)) == REG
- && GET_CODE (SET_DEST (body)) == REG
- && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body)))
- break;
-#endif
-
#ifdef HAVE_cc0
/* If this is a conditional branch, maybe modify it
if the cc's are in a nonstandard state
@@ -2209,15 +2233,12 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
do straightforwardly if the cc's were set up normally. */
if (cc_status.flags != 0
- && GET_CODE (insn) == JUMP_INSN
+ && JUMP_P (insn)
&& GET_CODE (body) == SET
&& SET_DEST (body) == pc_rtx
&& GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
- && GET_RTX_CLASS (GET_CODE (XEXP (SET_SRC (body), 0))) == '<'
- && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx
- /* This is done during prescan; it is not done again
- in final scan when prescan has been done. */
- && prescan >= 0)
+ && COMPARISON_P (XEXP (SET_SRC (body), 0))
+ && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx)
{
/* This function may alter the contents of its argument
and clear some of the cc_status.flags bits.
@@ -2258,7 +2279,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
{
rtx cond_rtx, then_rtx, else_rtx;
- if (GET_CODE (insn) != JUMP_INSN
+ if (!JUMP_P (insn)
&& GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)
{
cond_rtx = XEXP (SET_SRC (set), 0);
@@ -2317,14 +2338,16 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
emit them before the peephole. */
if (next != 0 && next != NEXT_INSN (insn))
{
- rtx prev = PREV_INSN (insn);
+ rtx note, prev = PREV_INSN (insn);
for (note = NEXT_INSN (insn); note != next;
note = NEXT_INSN (note))
- final_scan_insn (note, file, optimize, prescan, nopeepholes, seen);
+ final_scan_insn (note, file, optimize, nopeepholes, seen);
- /* In case this is prescan, put the notes
- in proper position for later rescan. */
+ /* Put the notes in the proper position for a later
+ rescan. For example, the SH target can do this
+ when generating a far jump in a delayed branch
+ sequence. */
note = NEXT_INSN (insn);
PREV_INSN (note) = prev;
NEXT_INSN (prev) = note;
@@ -2368,8 +2391,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
#ifdef HAVE_conditional_execution
if (GET_CODE (PATTERN (insn)) == COND_EXEC)
current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
- else
- current_insn_predicate = NULL_RTX;
#endif
#ifdef HAVE_cc0
@@ -2386,8 +2407,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
current_output_insn = debug_insn = insn;
#if defined (DWARF2_UNWIND_INFO)
- if (GET_CODE (insn) == CALL_INSN && dwarf2out_do_frame ())
- dwarf2out_frame_debug (insn);
+ if (CALL_P (insn) && dwarf2out_do_frame ())
+ dwarf2out_frame_debug (insn, false);
#endif
/* Find the proper template for this insn. */
@@ -2400,8 +2421,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
{
rtx prev;
- if (prev_nonnote_insn (insn) != last_ignored_compare)
- abort ();
+ gcc_assert (prev_nonnote_insn (insn) == last_ignored_compare);
/* We have already processed the notes between the setter and
the user. Make sure we don't process them again, this is
@@ -2411,7 +2431,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
prev != last_ignored_compare;
prev = PREV_INSN (prev))
{
- if (GET_CODE (prev) == NOTE)
+ if (NOTE_P (prev))
delete_insn (prev); /* Use delete_note. */
}
@@ -2432,55 +2452,41 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
/* This instruction should have been split in shorten_branches,
to ensure that we would have valid length info for the
splitees. */
- abort ();
+ gcc_unreachable ();
#endif
return new;
}
- if (prescan > 0)
- break;
-
-#ifdef IA64_UNWIND_INFO
- IA64_UNWIND_EMIT (asm_out_file, insn);
+#ifdef TARGET_UNWIND_INFO
+ /* ??? This will put the directives in the wrong place if
+ get_insn_template outputs assembly directly. However calling it
+ before get_insn_template breaks if the insns is split. */
+ targetm.asm_out.unwind_emit (asm_out_file, insn);
#endif
- /* Output assembler code from the template. */
+ /* Output assembler code from the template. */
output_asm_insn (template, recog_data.operand);
/* If necessary, report the effect that the instruction has on
the unwind info. We've already done this for delay slots
and call instructions. */
#if defined (DWARF2_UNWIND_INFO)
- if (GET_CODE (insn) == INSN
+ if (final_sequence == 0
#if !defined (HAVE_prologue)
&& !ACCUMULATE_OUTGOING_ARGS
#endif
- && final_sequence == 0
&& dwarf2out_do_frame ())
- dwarf2out_frame_debug (insn);
+ dwarf2out_frame_debug (insn, true);
#endif
-#if 0
- /* It's not at all clear why we did this and doing so used to
- interfere with tests that used REG_WAS_0 notes, which are
- now gone, so let's try with this out. */
-
- /* Mark this insn as having been output. */
- INSN_DELETED_P (insn) = 1;
-#endif
-
- /* Emit information for vtable gc. */
- note = find_reg_note (insn, REG_VTABLE_REF, NULL_RTX);
-
current_output_insn = debug_insn = 0;
}
}
return NEXT_INSN (insn);
}
-/* Output debugging info to the assembler file FILE
- based on the NOTE-insn INSN, assumed to be a line number. */
+/* Return whether a source line note needs to be emitted before INSN. */
static bool
notice_source_line (rtx insn)
@@ -2488,8 +2494,12 @@ notice_source_line (rtx insn)
const char *filename = insn_file (insn);
int linenum = insn_line (insn);
- if (filename && (filename != last_filename || last_linenum != linenum))
+ if (filename
+ && (force_source_line
+ || filename != last_filename
+ || last_linenum != linenum))
{
+ force_source_line = false;
last_filename = filename;
last_linenum = linenum;
high_block_linenum = MAX (last_linenum, high_block_linenum);
@@ -2518,7 +2528,7 @@ cleanup_subreg_operands (rtx insn)
recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i]);
else if (GET_CODE (recog_data.operand[i]) == PLUS
|| GET_CODE (recog_data.operand[i]) == MULT
- || GET_CODE (recog_data.operand[i]) == MEM)
+ || MEM_P (recog_data.operand[i]))
recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i]);
}
@@ -2528,7 +2538,7 @@ cleanup_subreg_operands (rtx insn)
*recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i]);
else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS
|| GET_CODE (*recog_data.dup_loc[i]) == MULT
- || GET_CODE (*recog_data.dup_loc[i]) == MEM)
+ || MEM_P (*recog_data.dup_loc[i]))
*recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i]);
}
}
@@ -2544,8 +2554,25 @@ alter_subreg (rtx *xp)
/* simplify_subreg does not remove subreg from volatile references.
We are required to. */
- if (GET_CODE (y) == MEM)
- *xp = adjust_address (y, GET_MODE (x), SUBREG_BYTE (x));
+ if (MEM_P (y))
+ {
+ int offset = SUBREG_BYTE (x);
+
+ /* For paradoxical subregs on big-endian machines, SUBREG_BYTE
+ contains 0 instead of the proper offset. See simplify_subreg. */
+ if (offset == 0
+ && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x)))
+ {
+ int difference = GET_MODE_SIZE (GET_MODE (y))
+ - GET_MODE_SIZE (GET_MODE (x));
+ if (WORDS_BIG_ENDIAN)
+ offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ offset += difference % UNITS_PER_WORD;
+ }
+
+ *xp = adjust_address (y, GET_MODE (x), offset);
+ }
else
{
rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
@@ -2553,14 +2580,12 @@ alter_subreg (rtx *xp)
if (new != 0)
*xp = new;
- /* Simplify_subreg can't handle some REG cases, but we have to. */
- else if (GET_CODE (y) == REG)
+ else if (REG_P (y))
{
- unsigned int regno = subreg_hard_regno (x, 1);
+ /* Simplify_subreg can't handle some REG cases, but we have to. */
+ unsigned int regno = subreg_regno (x);
*xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, SUBREG_BYTE (x));
}
- else
- abort ();
}
return *xp;
@@ -2576,11 +2601,13 @@ walk_alter_subreg (rtx *xp)
{
case PLUS:
case MULT:
+ case AND:
XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1));
break;
case MEM:
+ case ZERO_EXTEND:
XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
break;
@@ -2709,7 +2736,7 @@ alter_cond (rtx cond)
switch (GET_CODE (cond))
{
default:
- abort ();
+ gcc_unreachable ();
case NE:
PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);
@@ -2759,17 +2786,17 @@ alter_cond (rtx cond)
In an `asm', it's the user's fault; otherwise, the compiler's fault. */
void
-output_operand_lossage (const char *msgid, ...)
+output_operand_lossage (const char *cmsgid, ...)
{
char *fmt_string;
char *new_message;
const char *pfx_str;
va_list ap;
- va_start (ap, msgid);
+ va_start (ap, cmsgid);
- pfx_str = this_is_asm_operands ? _("invalid `asm': ") : "output_operand: ";
- asprintf (&fmt_string, "%s%s", pfx_str, _(msgid));
+ pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: ";
+ asprintf (&fmt_string, "%s%s", pfx_str, _(cmsgid));
vasprintf (&new_message, fmt_string, ap);
if (this_is_asm_operands)
@@ -2820,9 +2847,9 @@ get_mem_expr_from_op (rtx op, int *paddressp)
*paddressp = 0;
- if (GET_CODE (op) == REG)
+ if (REG_P (op))
return REG_EXPR (op);
- else if (GET_CODE (op) != MEM)
+ else if (!MEM_P (op))
return 0;
if (MEM_EXPR (op) != 0)
@@ -2841,8 +2868,8 @@ get_mem_expr_from_op (rtx op, int *paddressp)
&& (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp)))
return expr;
- while (GET_RTX_CLASS (GET_CODE (op)) == '1'
- || GET_RTX_CLASS (GET_CODE (op)) == '2')
+ while (GET_RTX_CLASS (GET_CODE (op)) == RTX_UNARY
+ || GET_RTX_CLASS (GET_CODE (op)) == RTX_BIN_ARITH)
op = XEXP (op, 0);
expr = get_mem_expr_from_op (op, &inner_addressp);
@@ -3021,61 +3048,66 @@ output_asm_insn (const char *template, rtx *operands)
else if (ISALPHA (*p))
{
int letter = *p++;
- c = atoi (p);
+ unsigned long opnum;
+ char *endptr;
+
+ opnum = strtoul (p, &endptr, 10);
- if (! ISDIGIT (*p))
- output_operand_lossage ("operand number missing after %%-letter");
- else if (this_is_asm_operands
- && (c < 0 || (unsigned int) c >= insn_noperands))
+ if (endptr == p)
+ output_operand_lossage ("operand number missing "
+ "after %%-letter");
+ else if (this_is_asm_operands && opnum >= insn_noperands)
output_operand_lossage ("operand number out of range");
else if (letter == 'l')
- output_asm_label (operands[c]);
+ output_asm_label (operands[opnum]);
else if (letter == 'a')
- output_address (operands[c]);
+ output_address (operands[opnum]);
else if (letter == 'c')
{
- if (CONSTANT_ADDRESS_P (operands[c]))
- output_addr_const (asm_out_file, operands[c]);
+ if (CONSTANT_ADDRESS_P (operands[opnum]))
+ output_addr_const (asm_out_file, operands[opnum]);
else
- output_operand (operands[c], 'c');
+ output_operand (operands[opnum], 'c');
}
else if (letter == 'n')
{
- if (GET_CODE (operands[c]) == CONST_INT)
+ if (GET_CODE (operands[opnum]) == CONST_INT)
fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
- - INTVAL (operands[c]));
+ - INTVAL (operands[opnum]));
else
{
putc ('-', asm_out_file);
- output_addr_const (asm_out_file, operands[c]);
+ output_addr_const (asm_out_file, operands[opnum]);
}
}
else
- output_operand (operands[c], letter);
+ output_operand (operands[opnum], letter);
- if (!opoutput[c])
- oporder[ops++] = c;
- opoutput[c] = 1;
+ if (!opoutput[opnum])
+ oporder[ops++] = opnum;
+ opoutput[opnum] = 1;
- while (ISDIGIT (c = *p))
- p++;
+ p = endptr;
+ c = *p;
}
/* % followed by a digit outputs an operand the default way. */
else if (ISDIGIT (*p))
{
- c = atoi (p);
- if (this_is_asm_operands
- && (c < 0 || (unsigned int) c >= insn_noperands))
+ unsigned long opnum;
+ char *endptr;
+
+ opnum = strtoul (p, &endptr, 10);
+ if (this_is_asm_operands && opnum >= insn_noperands)
output_operand_lossage ("operand number out of range");
else
- output_operand (operands[c], 0);
+ output_operand (operands[opnum], 0);
- if (!opoutput[c])
- oporder[ops++] = c;
- opoutput[c] = 1;
+ if (!opoutput[opnum])
+ oporder[ops++] = opnum;
+ opoutput[opnum] = 1;
- while (ISDIGIT (c = *p))
- p++;
+ p = endptr;
+ c = *p;
}
/* % followed by punctuation: output something for that
punctuation character alone, with no operand.
@@ -3110,12 +3142,12 @@ output_asm_label (rtx x)
if (GET_CODE (x) == LABEL_REF)
x = XEXP (x, 0);
- if (GET_CODE (x) == CODE_LABEL
- || (GET_CODE (x) == NOTE
+ if (LABEL_P (x)
+ || (NOTE_P (x)
&& NOTE_LINE_NUMBER (x) == NOTE_INSN_DELETED_LABEL))
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
else
- output_operand_lossage ("`%%l' operand isn't a label");
+ output_operand_lossage ("'%%l' operand isn't a label");
assemble_name (asm_out_file, buf);
}
@@ -3136,11 +3168,8 @@ output_operand (rtx x, int code ATTRIBUTE_UNUSED)
if (x && GET_CODE (x) == SUBREG)
x = alter_subreg (&x);
- /* If X is a pseudo-register, abort now rather than writing trash to the
- assembler file. */
-
- if (x && GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
- abort ();
+ /* X must not be a pseudo reg. */
+ gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
PRINT_OPERAND (asm_out_file, x, code);
}
@@ -3173,6 +3202,8 @@ output_addr_const (FILE *file, rtx x)
break;
case SYMBOL_REF:
+ if (SYMBOL_REF_DECL (x))
+ mark_decl_referenced (SYMBOL_REF_DECL (x));
#ifdef ASM_OUTPUT_SYMBOL_REF
ASM_OUTPUT_SYMBOL_REF (file, x);
#else
@@ -3437,7 +3468,7 @@ asm_fprintf (FILE *file, const char *p, ...)
ASM_FPRINTF_EXTENSIONS (file, argptr, p)
#endif
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -3584,8 +3615,8 @@ split_double (rtx value, rtx *first, rtx *second)
}
#endif
- *first = GEN_INT ((HOST_WIDE_INT) l[0]);
- *second = GEN_INT ((HOST_WIDE_INT) l[1]);
+ *first = GEN_INT (l[0]);
+ *second = GEN_INT (l[1]);
}
}
@@ -3602,12 +3633,12 @@ leaf_function_p (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if (GET_CODE (insn) == CALL_INSN
+ if (CALL_P (insn)
&& ! SIBLING_CALL_P (insn))
return 0;
- if (GET_CODE (insn) == INSN
+ if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE
- && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN
+ && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
&& ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
return 0;
}
@@ -3617,12 +3648,12 @@ leaf_function_p (void)
{
insn = XEXP (link, 0);
- if (GET_CODE (insn) == CALL_INSN
+ if (CALL_P (insn)
&& ! SIBLING_CALL_P (insn))
return 0;
- if (GET_CODE (insn) == INSN
+ if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE
- && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN
+ && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
&& ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
return 0;
}
@@ -3638,13 +3669,12 @@ int
final_forward_branch_p (rtx insn)
{
int insn_id, label_id;
- if (!uid_shuid)
- abort ();
+
+ gcc_assert (uid_shuid);
insn_id = INSN_SHUID (insn);
label_id = INSN_SHUID (JUMP_LABEL (insn));
/* We've hit some insns that does not have id information available. */
- if (!insn_id || !label_id)
- abort ();
+ gcc_assert (insn_id && label_id);
return insn_id < label_id;
}
@@ -3675,7 +3705,7 @@ only_leaf_regs_used (void)
if (current_function_uses_pic_offset_table
&& pic_offset_table_rtx != 0
- && GET_CODE (pic_offset_table_rtx) == REG
+ && REG_P (pic_offset_table_rtx)
&& ! permitted_reg_in_leaf_functions[REGNO (pic_offset_table_rtx)])
return 0;
@@ -3719,7 +3749,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
renumbered_regs would be 1 for an output-register;
they */
- if (GET_CODE (in_rtx) == REG)
+ if (REG_P (in_rtx))
{
int newreg;
@@ -3736,8 +3766,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
return;
}
newreg = LEAF_REG_REMAP (newreg);
- if (newreg < 0)
- abort ();
+ gcc_assert (newreg >= 0);
regs_ever_live[REGNO (in_rtx)] = 0;
regs_ever_live[newreg] = 1;
REGNO (in_rtx) = newreg;
@@ -3780,7 +3809,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
#endif
@@ -3816,7 +3845,7 @@ debug_flush_symbol_queue (void)
for (i = 0; i < symbol_queue_index; ++i)
{
- /* If we pushed queued symbols then such symbols are must be
+ /* If we pushed queued symbols then such symbols must be
output no matter what anyone else says. Specifically,
we need to make sure dbxout_symbol() thinks the symbol was
used and also we need to override TYPE_DECL_SUPPRESS_DEBUG
@@ -3866,3 +3895,192 @@ debug_free_queue (void)
symbol_queue_size = 0;
}
}
+
+/* Turn the RTL into assembly. */
+static unsigned int
+rest_of_handle_final (void)
+{
+ rtx x;
+ const char *fnname;
+
+ /* Get the function's name, as described by its RTL. This may be
+ different from the DECL_NAME name used in the source file. */
+
+ x = DECL_RTL (current_function_decl);
+ gcc_assert (MEM_P (x));
+ x = XEXP (x, 0);
+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
+ fnname = XSTR (x, 0);
+
+ assemble_start_function (current_function_decl, fnname);
+ final_start_function (get_insns (), asm_out_file, optimize);
+ final (get_insns (), asm_out_file, optimize);
+ final_end_function ();
+
+#ifdef TARGET_UNWIND_INFO
+ /* ??? The IA-64 ".handlerdata" directive must be issued before
+ the ".endp" directive that closes the procedure descriptor. */
+ output_function_exception_table ();
+#endif
+
+ assemble_end_function (current_function_decl, fnname);
+
+#ifndef TARGET_UNWIND_INFO
+ /* Otherwise, it feels unclean to switch sections in the middle. */
+ output_function_exception_table ();
+#endif
+
+ user_defined_section_attribute = false;
+
+ if (! quiet_flag)
+ fflush (asm_out_file);
+
+ /* Release all memory allocated by flow. */
+ free_basic_block_vars ();
+
+ /* Write DBX symbols if requested. */
+
+ /* Note that for those inline functions where we don't initially
+ know for certain that we will be generating an out-of-line copy,
+ the first invocation of this routine (rest_of_compilation) will
+ skip over this code by doing a `goto exit_rest_of_compilation;'.
+ Later on, wrapup_global_declarations will (indirectly) call
+ rest_of_compilation again for those inline functions that need
+ to have out-of-line copies generated. During that call, we
+ *will* be routed past here. */
+
+ timevar_push (TV_SYMOUT);
+ (*debug_hooks->function_decl) (current_function_decl);
+ timevar_pop (TV_SYMOUT);
+ return 0;
+}
+
+struct tree_opt_pass pass_final =
+{
+ NULL, /* name */
+ NULL, /* gate */
+ rest_of_handle_final, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_FINAL, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_ggc_collect, /* todo_flags_finish */
+ 0 /* letter */
+};
+
+
+static unsigned int
+rest_of_handle_shorten_branches (void)
+{
+ /* Shorten branches. */
+ shorten_branches (get_insns ());
+ return 0;
+}
+
+struct tree_opt_pass pass_shorten_branches =
+{
+ "shorten", /* name */
+ NULL, /* gate */
+ rest_of_handle_shorten_branches, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_FINAL, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
+
+
+static unsigned int
+rest_of_clean_state (void)
+{
+ rtx insn, next;
+
+ /* It is very important to decompose the RTL instruction chain here:
+ debug information keeps pointing into CODE_LABEL insns inside the function
+ body. If these remain pointing to the other insns, we end up preserving
+ whole RTL chain and attached detailed debug info in memory. */
+ for (insn = get_insns (); insn; insn = next)
+ {
+ next = NEXT_INSN (insn);
+ NEXT_INSN (insn) = NULL;
+ PREV_INSN (insn) = NULL;
+ }
+
+ /* In case the function was not output,
+ don't leave any temporary anonymous types
+ queued up for sdb output. */
+#ifdef SDB_DEBUGGING_INFO
+ if (write_symbols == SDB_DEBUG)
+ sdbout_types (NULL_TREE);
+#endif
+
+ reload_completed = 0;
+ epilogue_completed = 0;
+ flow2_completed = 0;
+ no_new_pseudos = 0;
+#ifdef STACK_REGS
+ regstack_completed = 0;
+#endif
+
+ /* Clear out the insn_length contents now that they are no
+ longer valid. */
+ init_insn_lengths ();
+
+ /* Show no temporary slots allocated. */
+ init_temp_slots ();
+
+ free_basic_block_vars ();
+ free_bb_for_insn ();
+
+
+ if (targetm.binds_local_p (current_function_decl))
+ {
+ int pref = cfun->preferred_stack_boundary;
+ if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary)
+ pref = cfun->stack_alignment_needed;
+ cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary
+ = pref;
+ }
+
+ /* Make sure volatile mem refs aren't considered valid operands for
+ arithmetic insns. We must call this here if this is a nested inline
+ function, since the above code leaves us in the init_recog state,
+ and the function context push/pop code does not save/restore volatile_ok.
+
+ ??? Maybe it isn't necessary for expand_start_function to call this
+ anymore if we do it here? */
+
+ init_recog_no_volatile ();
+
+ /* We're done with this function. Free up memory if we can. */
+ free_after_parsing (cfun);
+ free_after_compilation (cfun);
+ return 0;
+}
+
+struct tree_opt_pass pass_clean_state =
+{
+ NULL, /* name */
+ NULL, /* gate */
+ rest_of_clean_state, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_FINAL, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ PROP_rtl, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+ 0 /* letter */
+};
+
diff --git a/contrib/gcc/flags.h b/contrib/gcc/flags.h
index e947f2a..226fb60 100644
--- a/contrib/gcc/flags.h
+++ b/contrib/gcc/flags.h
@@ -1,6 +1,6 @@
/* Compilation switch flag definitions for GCC.
Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
- 2003
+ 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
@@ -17,18 +17,19 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef GCC_FLAGS_H
#define GCC_FLAGS_H
+#include "options.h"
+
enum debug_info_type
{
NO_DEBUG, /* Write no debug info. */
DBX_DEBUG, /* Write BSD .stabs for DBX (using dbxout.c). */
SDB_DEBUG, /* Write COFF for (old) SDB (using sdbout.c). */
- DWARF_DEBUG, /* Write Dwarf debug info (using dwarfout.c). */
DWARF2_DEBUG, /* Write Dwarf v2 debug info (using dwarf2out.c). */
XCOFF_DEBUG, /* Write IBM/Xcoff debug info (using dbxout.c). */
VMS_DEBUG, /* Write VMS debug info (using vmsdbgout.c). */
@@ -57,8 +58,30 @@ extern enum debug_info_level debug_info_level;
debugging information. */
extern bool use_gnu_debug_info_extensions;
-/* Nonzero means emit debugging information only for symbols which are used. */
-extern int flag_debug_only_used_symbols;
+/* Enumerate visibility settings. This is deliberately ordered from most
+ to least visibility. */
+#ifndef SYMBOL_VISIBILITY_DEFINED
+#define SYMBOL_VISIBILITY_DEFINED
+enum symbol_visibility
+{
+ VISIBILITY_DEFAULT,
+ VISIBILITY_PROTECTED,
+ VISIBILITY_HIDDEN,
+ VISIBILITY_INTERNAL
+};
+#endif
+
+/* The default visibility for all symbols (unless overridden). */
+extern enum symbol_visibility default_visibility;
+
+struct visibility_flags
+{
+ unsigned inpragma : 1; /* True when in #pragma GCC visibility. */
+ unsigned inlines_hidden : 1; /* True when -finlineshidden in effect. */
+};
+
+/* Global visibility options. */
+extern struct visibility_flags visibility_options;
/* Nonzero means do optimizations. -opt. */
@@ -68,90 +91,17 @@ extern int optimize;
extern int optimize_size;
-/* Don't print functions as they are compiled and don't print
- times taken by the various passes. -quiet. */
-
-extern int quiet_flag;
-
-/* Print memory still in use at end of compilation (which may have little
- to do with peak memory consumption). -fmem-report. */
-
-extern int mem_report;
-
-/* Don't print warning messages. -w. */
-
-extern bool inhibit_warnings;
-
-/* Don't suppress warnings from system headers. -Wsystem-headers. */
-
-extern bool warn_system_headers;
-
/* Do print extra warnings (such as for uninitialized variables).
-W/-Wextra. */
extern bool extra_warnings;
-/* If -Werror. */
-
-extern bool warnings_are_errors;
-
/* Nonzero to warn about unused variables, functions et.al. Use
set_Wunused() to update the -Wunused-* flags that correspond to the
-Wunused option. */
extern void set_Wunused (int setting);
-extern bool warn_unused_function;
-extern bool warn_unused_label;
-extern bool warn_unused_parameter;
-extern bool warn_unused_variable;
-extern bool warn_unused_value;
-
-/* Nonzero to warn about code which is never reached. */
-
-extern bool warn_notreached;
-
-/* Nonzero means warn if inline function is too large. */
-
-extern bool warn_inline;
-
-/* Nonzero to warn about variables used before they are initialized. */
-
-extern int warn_uninitialized;
-
-/* Nonzero means warn about all declarations which shadow others. */
-
-extern bool warn_shadow;
-
-/* Warn if a switch on an enum, that does not have a default case,
- fails to have a case for every enum value. */
-
-extern bool warn_switch;
-
-/* Warn if a switch does not have a default case. */
-
-extern bool warn_switch_default;
-
-/* Warn if a switch on an enum fails to have a case for every enum
- value (regardless of the presence or otherwise of a default case). */
-
-extern bool warn_switch_enum;
-
-/* Nonzero means warn about function definitions that default the return type
- or that use a null return and have a return-type other than void. */
-
-extern int warn_return_type;
-
-/* Warn about functions which might be candidates for attribute noreturn. */
-
-extern bool warn_missing_noreturn;
-
-/* Nonzero means warn about pointer casts that increase the required
- alignment of the target type (and might therefore lead to a crash
- due to a misaligned access). */
-
-extern bool warn_cast_align;
-
/* Nonzero means warn about any objects definitions whose size is larger
than N bytes. Also want about function definitions whose returned
values are larger than N bytes. The value N is in `larger_than_size'. */
@@ -159,69 +109,15 @@ extern bool warn_cast_align;
extern bool warn_larger_than;
extern HOST_WIDE_INT larger_than_size;
-/* Warn if a function returns an aggregate,
- since there are often incompatible calling conventions for doing this. */
-
-extern bool warn_aggregate_return;
-
-/* Warn if packed attribute on struct is unnecessary and inefficient. */
-
-extern bool warn_packed;
-
-/* Warn when gcc pads a structure to an alignment boundary. */
-
-extern bool warn_padded;
-
-/* Warn when an optimization pass is disabled. */
-
-extern bool warn_disabled_optimization;
-
-/* Nonzero means warn about uses of __attribute__((deprecated))
- declarations. */
-
-extern bool warn_deprecated_decl;
-
/* Nonzero means warn about constructs which might not be strict
aliasing safe. */
-extern bool warn_strict_aliasing;
-
-/* Nonzero if generating code to do profiling. */
-
-extern int profile_flag;
-
-/* Nonzero if generating code to profile program flow graph arcs. */
-
-extern int profile_arc_flag;
+extern int warn_strict_aliasing;
-/* Nonzero if value profile should be measured. */
+/* Nonzero means warn about optimizations which rely on undefined
+ signed overflow. */
-extern int flag_profile_values;
-
-/* Nonzero if generating info for gcov to calculate line test coverage. */
-
-extern int flag_test_coverage;
-
-/* Nonzero indicates that branch taken probabilities should be calculated. */
-
-extern int flag_branch_probabilities;
-
-/* Nonzero if basic blocks should be reordered. */
-
-extern int flag_reorder_blocks;
-
-/* Nonzero if functions should be reordered. */
-
-extern int flag_reorder_functions;
-
-/* Nonzero if registers should be renamed. */
-
-extern int flag_rename_registers;
-
-/* Nonzero for -pedantic switch: warn about anything
- that standard C forbids. */
-
-extern int pedantic;
+extern int warn_strict_overflow;
/* Temporarily suppress certain warnings.
This is set while reading code from a system header file. */
@@ -239,163 +135,20 @@ extern int flag_print_asm_name;
extern int flag_signed_char;
-/* Nonzero means give an enum type only as many bytes as it needs. */
+/* Nonzero means give an enum type only as many bytes as it needs. A value
+ of 2 means it has not yet been initialized. */
extern int flag_short_enums;
-/* Nonzero for -fcaller-saves: allocate values in regs that need to
- be saved across function calls, if that produces overall better code.
- Optional now, so people can test it. */
-
-extern int flag_caller_saves;
-
/* Nonzero for -fpcc-struct-return: return values the same way PCC does. */
extern int flag_pcc_struct_return;
-/* Nonzero for -fforce-mem: load memory value into a register
- before arithmetic on it. This makes better cse but slower compilation. */
-
-extern int flag_force_mem;
-
-/* Nonzero for -fforce-addr: load memory address into a register before
- reference to memory. This makes better cse but slower compilation. */
-
-extern int flag_force_addr;
-
-/* Nonzero for -fdefer-pop: don't pop args after each function call;
- instead save them up to pop many calls' args with one insns. */
-
-extern int flag_defer_pop;
-
-/* Nonzero for -ffloat-store: don't allocate floats and doubles
- in extended-precision registers. */
-
-extern int flag_float_store;
-
-/* Nonzero enables strength-reduction in loop.c. */
-
-extern int flag_strength_reduce;
-
-/* Nonzero enables loop unrolling in unroll.c. Only loops for which the
- number of iterations can be calculated at compile-time (UNROLL_COMPLETELY,
- UNROLL_MODULO) or at run-time (preconditioned to be UNROLL_MODULO) are
- unrolled. */
-
-extern int flag_old_unroll_loops;
-
-/* Nonzero enables loop unrolling in unroll.c. All loops are unrolled.
- This is generally not a win. */
-
-extern int flag_old_unroll_all_loops;
-
-/* Nonzero forces all invariant computations in loops to be moved
- outside the loop. */
-
-extern int flag_move_all_movables;
-
-/* Nonzero enables prefetch optimizations for arrays in loops. */
-
-extern int flag_prefetch_loop_arrays;
-
-/* Nonzero forces all general induction variables in loops to be
- strength reduced. */
-
-extern int flag_reduce_all_givs;
-
-/* Nonzero for -fcse-follow-jumps:
- have cse follow jumps to do a more extensive job. */
-
-extern int flag_cse_follow_jumps;
-
-/* Nonzero for -fcse-skip-blocks:
- have cse follow a branch around a block. */
-
-extern int flag_cse_skip_blocks;
-
-/* Nonzero for -fexpensive-optimizations:
- perform miscellaneous relatively-expensive optimizations. */
-extern int flag_expensive_optimizations;
-
-/* Nonzero for -fwritable-strings:
- store string constants in data segment and don't uniquize them. */
-
-extern int flag_writable_strings;
-
-/* Nonzero means don't put addresses of constant functions in registers.
- Used for compiling the Unix kernel, where strange substitutions are
- done on the assembly output. */
-
-extern int flag_no_function_cse;
-
-/* Nonzero for -fomit-frame-pointer:
- don't make a frame pointer in simple functions that don't require one. */
-
-extern int flag_omit_frame_pointer;
-
-/* Nonzero to inhibit use of define_optimization peephole opts. */
-
-extern int flag_no_peephole;
-
-/* Nonzero allows GCC to optimize sibling and tail recursive calls. */
-
-extern int flag_optimize_sibling_calls;
-
-/* Nonzero means the front end generally wants `errno' maintained by math
- operations, like built-in SQRT. */
-
-extern int flag_errno_math;
-
-/* Nonzero means that unsafe floating-point math optimizations are allowed
- for the sake of speed. IEEE compliance is not guaranteed, and operations
- are allowed to assume that their arguments and results are "normal"
- (e.g., nonnegative for SQRT). */
-
-extern int flag_unsafe_math_optimizations;
-
-/* Nonzero means that no NaNs or +-Infs are expected. */
-
-extern int flag_finite_math_only;
-
-/* Zero means that floating-point math operations cannot generate a
- (user-visible) trap. This is the case, for example, in nonstop
- IEEE 754 arithmetic. */
-
-extern int flag_trapping_math;
-
-/* Nonzero means disable transformations that assume default floating
- point rounding behavior. */
-
-extern int flag_rounding_math;
-
/* 0 means straightforward implementation of complex divide acceptable.
1 means wide ranges of inputs must work for complex divide.
- 2 means C99-like requirements for complex divide (not yet implemented). */
-
-extern int flag_complex_divide_method;
-
-/* Nonzero means to run loop optimizations twice. */
-
-extern int flag_rerun_loop_opt;
-
-/* Nonzero means make functions that look like good inline candidates
- go inline. */
-
-extern int flag_inline_functions;
-
-/* Nonzero for -fkeep-inline-functions: even if we make a function
- go inline everywhere, keep its definition around for debugging
- purposes. */
+ 2 means C99-like requirements for complex multiply and divide. */
-extern int flag_keep_inline_functions;
-
-/* Nonzero means that functions declared `inline' will be treated
- as `static'. Prevents generation of zillions of copies of unused
- static inline functions; instead, `inlines' are written out
- only when actually used. Used in conjunction with -g. Also
- does the right thing with #pragma interface. */
-
-extern int flag_no_inline;
+extern int flag_complex_method;
/* Nonzero means that we don't want inlining by virtue of -fno-inline,
not just because the tree inliner turned us off. */
@@ -404,69 +157,12 @@ extern int flag_really_no_inline;
/* Nonzero if we are only using compiler to check syntax errors. */
-extern int flag_syntax_only;
+extern int rtl_dump_and_exit;
/* Nonzero means we should save auxiliary info into a .X file. */
extern int flag_gen_aux_info;
-/* Nonzero means make the text shared if supported. */
-
-extern int flag_shared_data;
-
-/* flag_schedule_insns means schedule insns within basic blocks (before
- local_alloc).
- flag_schedule_insns_after_reload means schedule insns after
- global_alloc. */
-
-extern int flag_schedule_insns;
-extern int flag_schedule_insns_after_reload;
-extern int flag_sched2_use_superblocks;
-extern int flag_sched2_use_traces;
-
-/* The following flags have effect only for scheduling before register
- allocation:
-
- flag_schedule_interblock means schedule insns across basic blocks.
- flag_schedule_speculative means allow speculative motion of non-load insns.
- flag_schedule_speculative_load means allow speculative motion of some
- load insns.
- flag_schedule_speculative_load_dangerous allows speculative motion of more
- load insns. */
-
-extern int flag_schedule_interblock;
-extern int flag_schedule_speculative;
-extern int flag_schedule_speculative_load;
-extern int flag_schedule_speculative_load_dangerous;
-
-/* The following flags have an effect during scheduling after register
- allocation:
-
- sched_stalled_insns means that insns can be moved prematurely from the queue
- of stalled insns into the ready list.
-
- sched_stalled_insns_dep controls how many recently scheduled cycles will
- be examined for a dependency on a stalled insn that is candidate for
- premature removal from the queue of stalled insns into the ready list (has
- an effect only if the flag 'sched_stalled_insns' is set). */
-
-extern int flag_sched_stalled_insns;
-extern int flag_sched_stalled_insns_dep;
-
-/* flag_branch_on_count_reg means try to replace add-1,compare,branch tupple
- by a cheaper branch, on a count register. */
-extern int flag_branch_on_count_reg;
-
-/* This option is set to 1 on -fsingle-precision-constant option which is
- used to convert the floating point constants to single precision
- constants. */
-
-extern int flag_single_precision_constant;
-
-/* Nonzero means put things in delayed-branch slots if supported. */
-
-extern int flag_delayed_branch;
-
/* Nonzero means suppress output of instruction numbers and line number
notes in debugging dumps. */
@@ -477,63 +173,11 @@ extern int flag_dump_unnumbered;
extern int flag_pedantic_errors;
-/* Nonzero means generate position-independent code. 1 vs 2 for a
- target-dependent "small" or "large" mode. */
-
-extern int flag_pic;
-
-/* Nonzero if we are compiling position independent code for executable.
- 1 vs 2 for a target-dependent "small" or "large" mode. */
-
-extern int flag_pie;
-
/* Nonzero if we are compiling code for a shared library, zero for
executable. */
extern int flag_shlib;
-/* Nonzero means generate extra code for exception handling and enable
- exception handling. */
-
-extern int flag_exceptions;
-
-/* Nonzero means generate frame unwind info table when supported. */
-
-extern int flag_unwind_tables;
-
-/* Nonzero means generate frame unwind info table exact at each insn boundary. */
-
-extern int flag_asynchronous_unwind_tables;
-
-/* Nonzero means don't place uninitialized global data in common storage
- by default. */
-
-extern int flag_no_common;
-
-/* -finhibit-size-directive inhibits output of .size for ELF.
- This is used only for compiling crtstuff.c,
- and it may be extended to other effects
- needed for crtstuff.c on other systems. */
-extern int flag_inhibit_size_directive;
-
-/* Nonzero means place each function into its own section on those platforms
- which support arbitrary section names and unlimited numbers of sections. */
-
-extern int flag_function_sections;
-
-/* ... and similar for data. */
-
-extern int flag_data_sections;
-
-/* -fverbose-asm causes extra commentary information to be produced in
- the generated assembly code (to make it more readable). This option
- is generally only of use to those who actually need to read the
- generated assembly code (perhaps while debugging the compiler itself).
- -fno-verbose-asm, the default, causes the extra information
- to not be added and is useful when comparing two assembler files. */
-
-extern int flag_verbose_asm;
-
/* -dA causes debug information to be produced in
the generated assembly code (to make it more readable). This option
is generally only of use to those who actually need to read the
@@ -543,56 +187,11 @@ extern int flag_verbose_asm;
extern int flag_debug_asm;
-extern int flag_dump_rtl_in_asm;
-
-/* Greater than zero if user symbols are prepended by a leading underscore
- in generated assembly code. */
-extern int flag_leading_underscore;
+/* Generate code for GNU or NeXT Objective-C runtime environment. */
-/* Tag all structures with __attribute__(packed) */
-extern int flag_pack_struct;
+extern int flag_next_runtime;
-/* This flag is only tested if alias checking is enabled.
- 0 if pointer arguments may alias each other. True in C.
- 1 if pointer arguments may not alias each other but may alias
- global variables.
- 2 if pointer arguments may not alias each other and may not
- alias global variables. True in Fortran.
- The value is ignored if flag_alias_check is 0. */
-extern int flag_argument_noalias;
-
-/* Nonzero if we should do (language-dependent) alias analysis.
- Typically, this analysis will assume that expressions of certain
- types do not alias expressions of certain other types. Only used
- if alias analysis (in general) is enabled. */
-extern int flag_strict_aliasing;
-
-/* Emit code to probe the stack, to help detect stack overflow; also
- may cause large objects to be allocated dynamically. */
-extern int flag_stack_check;
-
-/* Do the full regmove optimization pass. */
-extern int flag_regmove;
-
-/* Instrument functions with calls at entry and exit, for profiling. */
-extern int flag_instrument_function_entry_exit;
-
-/* Perform a peephole pass before sched2. */
-extern int flag_peephole2;
-
-/* Try to guess branch probabilities. */
-extern int flag_guess_branch_prob;
-
-/* -fcheck-bounds causes gcc to generate array bounds checks.
- For C, C++ and ObjC: defaults off.
- For Java: defaults to on.
- For Fortran: defaults to off. */
-extern int flag_bounds_check;
-
-/* This will attempt to merge constant section constants, if 1 only
- string constants and constants from constant pool, if 2 also constant
- variables. */
-extern int flag_merge_constants;
+extern int flag_dump_rtl_in_asm;
/* If one, renumber instruction UIDs to reduce the number of
unused UIDs if there are a lot of instructions. If greater than
@@ -607,13 +206,6 @@ extern int flag_renumber_insns;
extern int frame_pointer_needed;
-/* Nonzero if the generated code should trap on signed overflow
- for PLUS / SUB / MULT. */
-extern int flag_trapv;
-
-/* Nonzero if the signed arithmetic overflow should wrap around. */
-extern int flag_wrapv;
-
/* Nonzero if subexpressions must be evaluated from left-to-right. */
extern int flag_evaluation_order;
@@ -626,16 +218,12 @@ extern bool g_switch_set;
For each variable, there is an _log variant which is the power
of two not less than the variable, for .align output. */
-extern int align_loops;
extern int align_loops_log;
extern int align_loops_max_skip;
-extern int align_jumps;
extern int align_jumps_log;
extern int align_jumps_max_skip;
-extern int align_labels;
extern int align_labels_log;
extern int align_labels_max_skip;
-extern int align_functions;
extern int align_functions_log;
/* Like align_functions_log above, but used by front-ends to force the
@@ -653,92 +241,26 @@ enum graph_dump_types
};
extern enum graph_dump_types graph_dump_format;
-/* Nonzero means ignore `#ident' directives. 0 means handle them.
- On SVR4 targets, it also controls whether or not to emit a
- string identifying the compiler. */
-
-extern int flag_no_ident;
-
-/* Nonzero means perform global CSE. */
-
-extern int flag_gcse;
-
-/* Nonzero if we want to perform enhanced load motion during gcse. */
-
-extern int flag_gcse_lm;
-
-/* Nonzero if we want to perform store motion after gcse. */
-
-extern int flag_gcse_sm;
-
-/* Nonzero if we want to perform redundant load-after-store elimination
- in gcse. */
-
-extern int flag_gcse_las;
-
-/* Nonzero if value histograms should be used to optimize code. */
-extern int flag_value_profile_transformations;
-
-/* Perform branch target register optimization before prologue / epilogue
- threading. */
-
-extern int flag_branch_target_load_optimize;
-
-/* Perform branch target register optimization after prologue / epilogue
- threading and jump2. */
-
-extern int flag_branch_target_load_optimize2;
-
-
-/* Nonzero means we should do dwarf2 duplicate elimination. */
-
-extern int flag_eliminate_dwarf2_dups;
-
-/* Nonzero means we should do unused type elimination. */
-
-extern int flag_eliminate_unused_debug_types;
-
/* Nonzero means to collect statistics which might be expensive
and to print them when we are done. */
extern int flag_detailed_statistics;
-/* Nonzero means enable synchronous exceptions for non-call instructions. */
-extern int flag_non_call_exceptions;
-
-/* Nonzero means put zero initialized data in the bss section. */
-extern int flag_zero_initialized_in_bss;
-
-/* Nonzero means disable transformations observable by signaling NaNs. */
-extern int flag_signaling_nans;
-
-extern int flag_unit_at_a_time;
-
-extern int flag_web;
-
/* Nonzero means that we defer emitting functions until they are actually
used. */
extern int flag_remove_unreachable_functions;
+/* Nonzero if we should track variables. */
+extern int flag_var_tracking;
+
+/* True if flag_speculative_prefetching was set by user. Used to suppress
+ warning message in case flag was set by -fprofile-{generate,use}. */
+extern bool flag_speculative_prefetching_set;
+
/* A string that's used when a random name is required. NULL means
to make it really random. */
extern const char *flag_random_seed;
-/* The version of the C++ ABI in use. The following values are
- allowed:
-
- 0: The version of the ABI believed most conformant with the
- C++ ABI specification. This ABI may change as bugs are
- discovered and fixed. Therefore, 0 will not necessarily
- indicate the same ABI in different versions of G++.
-
- 1: The version of the ABI first used in G++ 3.2.
-
- Additional positive integers will be assigned as new versions of
- the ABI become the default version of the ABI. */
-
-extern int flag_abi_version;
-
/* Returns TRUE if generated code should match ABI version N or
greater is in use. */
@@ -747,7 +269,7 @@ extern int flag_abi_version;
/* True if the given mode has a NaN representation and the treatment of
NaN operands is important. Certain optimizations, such as folding
- x * 0 into x, are not correct for NaN operands, and are normally
+ x * 0 into 0, are not correct for NaN operands, and are normally
disabled for modes with NaNs. The user can ask for them to be
done anyway using the -funsafe-math-optimizations switch. */
#define HONOR_NANS(MODE) \
@@ -771,4 +293,53 @@ extern int flag_abi_version;
#define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
(MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && flag_rounding_math)
+/* True if overflow wraps around for the given integral type. That
+ is, TYPE_MAX + 1 == TYPE_MIN. */
+#define TYPE_OVERFLOW_WRAPS(TYPE) \
+ (TYPE_UNSIGNED (TYPE) || flag_wrapv)
+
+/* True if overflow is undefined for the given integral type. We may
+ optimize on the assumption that values in the type never overflow.
+
+ IMPORTANT NOTE: Any optimization based on TYPE_OVERFLOW_UNDEFINED
+ must issue a warning based on warn_strict_overflow. In some cases
+ it will be appropriate to issue the warning immediately, and in
+ other cases it will be appropriate to simply set a flag and let the
+ caller decide whether a warning is appropriate or not. */
+#define TYPE_OVERFLOW_UNDEFINED(TYPE) \
+ (!TYPE_UNSIGNED (TYPE) && !flag_wrapv && !flag_trapv && flag_strict_overflow)
+
+/* True if overflow for the given integral type should issue a
+ trap. */
+#define TYPE_OVERFLOW_TRAPS(TYPE) \
+ (!TYPE_UNSIGNED (TYPE) && flag_trapv)
+
+/* Names for the different levels of -Wstrict-overflow=N. The numeric
+ values here correspond to N. */
+
+enum warn_strict_overflow_code
+{
+ /* Overflow warning that should be issued with -Wall: a questionable
+ construct that is easy to avoid even when using macros. Example:
+ folding (x + CONSTANT > x) to 1. */
+ WARN_STRICT_OVERFLOW_ALL = 1,
+ /* Overflow warning about folding a comparison to a constant because
+ of undefined signed overflow, other than cases covered by
+ WARN_STRICT_OVERFLOW_ALL. Example: folding (abs (x) >= 0) to 1
+ (this is false when x == INT_MIN). */
+ WARN_STRICT_OVERFLOW_CONDITIONAL = 2,
+ /* Overflow warning about changes to comparisons other than folding
+ them to a constant. Example: folding (x + 1 > 1) to (x > 0). */
+ WARN_STRICT_OVERFLOW_COMPARISON = 3,
+ /* Overflow warnings not covered by the above cases. Example:
+ folding ((x * 10) / 5) to (x * 2). */
+ WARN_STRICT_OVERFLOW_MISC = 4,
+ /* Overflow warnings about reducing magnitude of constants in
+ comparison. Example: folding (x + 2 > y) to (x + 1 >= y). */
+ WARN_STRICT_OVERFLOW_MAGNITUDE = 5
+};
+
+/* Whether to emit an overflow warning whose code is C. */
+#define issue_strict_overflow_warning(c) (warn_strict_overflow >= (int) (c))
+
#endif /* ! GCC_FLAGS_H */
diff --git a/contrib/gcc/ginclude/stdarg.h b/contrib/gcc/ginclude/stdarg.h
index f178505..c9ddd6b 100644
--- a/contrib/gcc/ginclude/stdarg.h
+++ b/contrib/gcc/ginclude/stdarg.h
@@ -14,8 +14,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
diff --git a/contrib/gcc/ginclude/stddef.h b/contrib/gcc/ginclude/stddef.h
index 03bfbf9..7e61795 100644
--- a/contrib/gcc/ginclude/stddef.h
+++ b/contrib/gcc/ginclude/stddef.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 1989, 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1997, 1998, 1999, 2000, 2002, 2004
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -14,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
@@ -295,7 +296,7 @@ typedef _BSD_RUNE_T_ rune_t;
#define _BSD_WCHAR_T_DEFINED_
#define _BSD_RUNE_T_DEFINED_ /* Darwin */
#if defined (__FreeBSD__) && (__FreeBSD__ < 5)
-/* Why is this file so hard to maintain properly? In constrast to
+/* Why is this file so hard to maintain properly? In contrast to
the comment above regarding BSD/386 1.1, on FreeBSD for as long
as the symbol has existed, _BSD_RUNE_T_ must not stay defined or
redundant typedefs will occur when stdlib.h is included after this file. */
@@ -410,16 +411,8 @@ typedef __WINT_TYPE__ wint_t;
#ifdef _STDDEF_H
/* Offset of member MEMBER in a struct of type TYPE. */
-#ifndef __cplusplus
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#else
-/* The cast to "char &" below avoids problems with user-defined
- "operator &", which can appear in a POD type. */
-#define offsetof(TYPE, MEMBER) \
- (__offsetof__ (reinterpret_cast <size_t> \
- (&reinterpret_cast <const volatile char &> \
- (static_cast<TYPE *> (0)->MEMBER))))
-#endif /* C++ */
+#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
+
#endif /* _STDDEF_H was defined this time */
#endif /* !_STDDEF_H && !_STDDEF_H_ && !_ANSI_STDDEF_H && !__STDDEF_H__
diff --git a/contrib/gcc/libgcc2.c b/contrib/gcc/libgcc2.c
index 4f45b09..851bdd0 100644
--- a/contrib/gcc/libgcc2.c
+++ b/contrib/gcc/libgcc2.c
@@ -1,7 +1,7 @@
/* More subroutines needed by GCC output code on some machines. */
/* Compile this one with gcc. */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -26,33 +26,42 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
-
-/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
- supposedly valid even though this is a "target" file. */
-#include "auto-host.h"
-
-/* It is incorrect to include config.h here, because this file is being
- compiled for the target, and hence definitions concerning only the host
- do not apply. */
#include "tconfig.h"
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
-/* Don't use `fancy_abort' here even if config.h says to use it. */
-#ifdef abort
-#undef abort
-#endif
-
#ifdef HAVE_GAS_HIDDEN
#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
#else
#define ATTRIBUTE_HIDDEN
#endif
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#endif
+
+/* Work out the largest "word" size that we can deal with on this target. */
+#if MIN_UNITS_PER_WORD > 4
+# define LIBGCC2_MAX_UNITS_PER_WORD 8
+#elif (MIN_UNITS_PER_WORD > 2 \
+ || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32))
+# define LIBGCC2_MAX_UNITS_PER_WORD 4
+#else
+# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
+#endif
+
+/* Work out what word size we are using for this compilation.
+ The value can be set on the command line. */
+#ifndef LIBGCC2_UNITS_PER_WORD
+#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
+#endif
+
+#if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD
+
#include "libgcc2.h"
#ifdef DECLARE_LIBRARY_RENAMES
@@ -148,13 +157,12 @@ __subvDI3 (DWtype a, DWtype b)
#endif
#ifdef L_mulvsi3
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
Wtype
__mulvSI3 (Wtype a, Wtype b)
{
const DWtype w = (DWtype) a * (DWtype) b;
- if ((Wtype) (w >> WORD_SIZE) != (Wtype) w >> (WORD_SIZE - 1))
+ if ((Wtype) (w >> W_TYPE_SIZE) != (Wtype) w >> (W_TYPE_SIZE - 1))
abort ();
return w;
@@ -273,7 +281,6 @@ __absvDI2 (DWtype a)
#endif
#ifdef L_mulvdi3
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
DWtype
__mulvDI3 (DWtype u, DWtype v)
{
@@ -282,10 +289,10 @@ __mulvDI3 (DWtype u, DWtype v)
const DWunion uu = {.ll = u};
const DWunion vv = {.ll = v};
- if (__builtin_expect (uu.s.high == uu.s.low >> (WORD_SIZE - 1), 1))
+ if (__builtin_expect (uu.s.high == uu.s.low >> (W_TYPE_SIZE - 1), 1))
{
/* u fits in a single Wtype. */
- if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
+ if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
{
/* v fits in a single Wtype as well. */
/* A single multiplication. No overflow risk. */
@@ -304,7 +311,7 @@ __mulvDI3 (DWtype u, DWtype v)
if (uu.s.low < 0)
w1.ll -= vv.ll;
w1.ll += (UWtype) w0.s.high;
- if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1))
+ if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
{
w0.s.high = w1.s.low;
return w0.ll;
@@ -313,7 +320,7 @@ __mulvDI3 (DWtype u, DWtype v)
}
else
{
- if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
+ if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
{
/* v fits into a single Wtype. */
/* Two multiplications. */
@@ -327,7 +334,7 @@ __mulvDI3 (DWtype u, DWtype v)
if (vv.s.low < 0)
w1.ll -= uu.ll;
w1.ll += (UWtype) w0.s.high;
- if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1))
+ if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
{
w0.s.high = w1.s.low;
return w0.ll;
@@ -487,7 +494,6 @@ __ashrdi3 (DWtype u, word_type b)
#ifdef L_ffssi2
#undef int
-extern int __ffsSI2 (UWtype u);
int
__ffsSI2 (UWtype u)
{
@@ -503,7 +509,6 @@ __ffsSI2 (UWtype u)
#ifdef L_ffsdi2
#undef int
-extern int __ffsDI2 (DWtype u);
int
__ffsDI2 (DWtype u)
{
@@ -560,16 +565,16 @@ __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
{
if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
{
- /* dividend, divisor, and quotient are nonnegative */
+ /* Dividend, divisor, and quotient are nonnegative. */
sdiv_qrnnd (q, r, a1, a0, d);
}
else
{
- /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
+ /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d. */
sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
- /* Divide (c1*2^32 + c0) by d */
+ /* Divide (c1*2^32 + c0) by d. */
sdiv_qrnnd (q, r, c1, c0, d);
- /* Add 2^31 to quotient */
+ /* Add 2^31 to quotient. */
q += (UWtype) 1 << (W_TYPE_SIZE - 1);
}
}
@@ -665,7 +670,7 @@ __udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
#endif
#ifdef L_clz
-const UQItype __clz_tab[] =
+const UQItype __clz_tab[256] =
{
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
@@ -674,13 +679,12 @@ const UQItype __clz_tab[] =
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
};
#endif
#ifdef L_clzsi2
#undef int
-extern int __clzSI2 (UWtype x);
int
__clzSI2 (UWtype x)
{
@@ -694,7 +698,6 @@ __clzSI2 (UWtype x)
#ifdef L_clzdi2
#undef int
-extern int __clzDI2 (UDWtype x);
int
__clzDI2 (UDWtype x)
{
@@ -714,7 +717,6 @@ __clzDI2 (UDWtype x)
#ifdef L_ctzsi2
#undef int
-extern int __ctzSI2 (UWtype x);
int
__ctzSI2 (UWtype x)
{
@@ -728,7 +730,6 @@ __ctzSI2 (UWtype x)
#ifdef L_ctzdi2
#undef int
-extern int __ctzDI2 (UDWtype x);
int
__ctzDI2 (UDWtype x)
{
@@ -746,13 +747,8 @@ __ctzDI2 (UDWtype x)
}
#endif
-#if (defined (L_popcountsi2) || defined (L_popcountdi2) \
- || defined (L_popcount_tab))
-extern const UQItype __popcount_tab[] ATTRIBUTE_HIDDEN;
-#endif
-
#ifdef L_popcount_tab
-const UQItype __popcount_tab[] =
+const UQItype __popcount_tab[256] =
{
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
@@ -761,17 +757,16 @@ const UQItype __popcount_tab[] =
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
- 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
};
#endif
#ifdef L_popcountsi2
#undef int
-extern int __popcountSI2 (UWtype x);
int
__popcountSI2 (UWtype x)
{
- UWtype i, ret = 0;
+ int i, ret = 0;
for (i = 0; i < W_TYPE_SIZE; i += 8)
ret += __popcount_tab[(x >> i) & 0xff];
@@ -782,11 +777,10 @@ __popcountSI2 (UWtype x)
#ifdef L_popcountdi2
#undef int
-extern int __popcountDI2 (UDWtype x);
int
__popcountDI2 (UDWtype x)
{
- UWtype i, ret = 0;
+ int i, ret = 0;
for (i = 0; i < 2*W_TYPE_SIZE; i += 8)
ret += __popcount_tab[(x >> i) & 0xff];
@@ -797,7 +791,6 @@ __popcountDI2 (UDWtype x)
#ifdef L_paritysi2
#undef int
-extern int __paritySI2 (UWtype x);
int
__paritySI2 (UWtype x)
{
@@ -819,7 +812,6 @@ __paritySI2 (UWtype x)
#ifdef L_paritydi2
#undef int
-extern int __parityDI2 (UDWtype x);
int
__parityDI2 (UDWtype x)
{
@@ -1101,7 +1093,7 @@ __moddi3 (DWtype u, DWtype v)
if (vv.s.high < 0)
vv.ll = -vv.ll;
- (void) __udivmoddi4 (uu.ll, vv.ll, &w);
+ (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
if (c)
w = -w;
@@ -1167,10 +1159,7 @@ __ucmpdi2 (DWtype a, DWtype b)
}
#endif
-#if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_fixunstfdi) && LIBGCC2_HAS_TF_MODE
DWtype
__fixunstfDI (TFtype a)
{
@@ -1178,11 +1167,11 @@ __fixunstfDI (TFtype a)
return 0;
/* Compute high word of result, as a flonum. */
- const TFtype b = (a / HIGH_WORD_COEFF);
+ const TFtype b = (a / Wtype_MAXp1_F);
/* Convert that to fixed (but not to DWtype!),
and shift it into the high word. */
UDWtype v = (UWtype) b;
- v <<= WORD_SIZE;
+ v <<= W_TYPE_SIZE;
/* Remove high part from the TFtype, leaving the low part as flonum. */
a -= (TFtype)v;
/* Convert that to fixed (but not to DWtype!) and add it in.
@@ -1196,7 +1185,7 @@ __fixunstfDI (TFtype a)
}
#endif
-#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+#if defined(L_fixtfdi) && LIBGCC2_HAS_TF_MODE
DWtype
__fixtfdi (TFtype a)
{
@@ -1206,10 +1195,7 @@ __fixtfdi (TFtype a)
}
#endif
-#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_fixunsxfdi) && LIBGCC2_HAS_XF_MODE
DWtype
__fixunsxfDI (XFtype a)
{
@@ -1217,11 +1203,11 @@ __fixunsxfDI (XFtype a)
return 0;
/* Compute high word of result, as a flonum. */
- const XFtype b = (a / HIGH_WORD_COEFF);
+ const XFtype b = (a / Wtype_MAXp1_F);
/* Convert that to fixed (but not to DWtype!),
and shift it into the high word. */
UDWtype v = (UWtype) b;
- v <<= WORD_SIZE;
+ v <<= W_TYPE_SIZE;
/* Remove high part from the XFtype, leaving the low part as flonum. */
a -= (XFtype)v;
/* Convert that to fixed (but not to DWtype!) and add it in.
@@ -1235,7 +1221,7 @@ __fixunsxfDI (XFtype a)
}
#endif
-#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#if defined(L_fixxfdi) && LIBGCC2_HAS_XF_MODE
DWtype
__fixxfdi (XFtype a)
{
@@ -1245,29 +1231,26 @@ __fixxfdi (XFtype a)
}
#endif
-#ifdef L_fixunsdfdi
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_fixunsdfdi) && LIBGCC2_HAS_DF_MODE
DWtype
__fixunsdfDI (DFtype a)
{
/* Get high part of result. The division here will just moves the radix
point and will not cause any rounding. Then the conversion to integral
type chops result as desired. */
- const UWtype hi = a / HIGH_WORD_COEFF;
+ const UWtype hi = a / Wtype_MAXp1_F;
/* Get low part of result. Convert `hi' to floating type and scale it back,
then subtract this from the number being converted. This leaves the low
part. Convert that to integral type. */
- const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
+ const UWtype lo = a - (DFtype) hi * Wtype_MAXp1_F;
/* Assemble result from the two parts. */
- return ((UDWtype) hi << WORD_SIZE) | lo;
+ return ((UDWtype) hi << W_TYPE_SIZE) | lo;
}
#endif
-#ifdef L_fixdfdi
+#if defined(L_fixdfdi) && LIBGCC2_HAS_DF_MODE
DWtype
__fixdfdi (DFtype a)
{
@@ -1277,34 +1260,71 @@ __fixdfdi (DFtype a)
}
#endif
-#ifdef L_fixunssfdi
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE
DWtype
-__fixunssfDI (SFtype original_a)
+__fixunssfDI (SFtype a)
{
+#if LIBGCC2_HAS_DF_MODE
/* Convert the SFtype to a DFtype, because that is surely not going
to lose any bits. Some day someone else can write a faster version
that avoids converting to DFtype, and verify it really works right. */
- const DFtype a = original_a;
+ const DFtype dfa = a;
/* Get high part of result. The division here will just moves the radix
point and will not cause any rounding. Then the conversion to integral
type chops result as desired. */
- const UWtype hi = a / HIGH_WORD_COEFF;
+ const UWtype hi = dfa / Wtype_MAXp1_F;
/* Get low part of result. Convert `hi' to floating type and scale it back,
then subtract this from the number being converted. This leaves the low
part. Convert that to integral type. */
- const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
+ const UWtype lo = dfa - (DFtype) hi * Wtype_MAXp1_F;
/* Assemble result from the two parts. */
- return ((UDWtype) hi << WORD_SIZE) | lo;
+ return ((UDWtype) hi << W_TYPE_SIZE) | lo;
+#elif FLT_MANT_DIG < W_TYPE_SIZE
+ if (a < 1)
+ return 0;
+ if (a < Wtype_MAXp1_F)
+ return (UWtype)a;
+ if (a < Wtype_MAXp1_F * Wtype_MAXp1_F)
+ {
+ /* Since we know that there are fewer significant bits in the SFmode
+ quantity than in a word, we know that we can convert out all the
+ significant bits in one step, and thus avoid losing bits. */
+
+ /* ??? This following loop essentially performs frexpf. If we could
+ use the real libm function, or poke at the actual bits of the fp
+ format, it would be significantly faster. */
+
+ UWtype shift = 0, counter;
+ SFtype msb;
+
+ a /= Wtype_MAXp1_F;
+ for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1)
+ {
+ SFtype counterf = (UWtype)1 << counter;
+ if (a >= counterf)
+ {
+ shift |= counter;
+ a /= counterf;
+ }
+ }
+
+ /* Rescale into the range of one word, extract the bits of that
+ one word, and shift the result into position. */
+ a *= Wtype_MAXp1_F;
+ counter = a;
+ return (DWtype)counter << shift;
+ }
+ return -1;
+#else
+# error
+#endif
}
#endif
-#ifdef L_fixsfdi
+#if defined(L_fixsfdi) && LIBGCC2_HAS_SF_MODE
DWtype
__fixsfdi (SFtype a)
{
@@ -1314,102 +1334,280 @@ __fixsfdi (SFtype a)
}
#endif
-#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_floatdixf) && LIBGCC2_HAS_XF_MODE
XFtype
__floatdixf (DWtype u)
{
- XFtype d = (Wtype) (u >> WORD_SIZE);
- d *= HIGH_HALFWORD_COEFF;
- d *= HIGH_HALFWORD_COEFF;
- d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
-
+#if W_TYPE_SIZE > XF_SIZE
+# error
+#endif
+ XFtype d = (Wtype) (u >> W_TYPE_SIZE);
+ d *= Wtype_MAXp1_F;
+ d += (UWtype)u;
return d;
}
#endif
-#if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
+#if defined(L_floatundixf) && LIBGCC2_HAS_XF_MODE
+XFtype
+__floatundixf (UDWtype u)
+{
+#if W_TYPE_SIZE > XF_SIZE
+# error
+#endif
+ XFtype d = (UWtype) (u >> W_TYPE_SIZE);
+ d *= Wtype_MAXp1_F;
+ d += (UWtype)u;
+ return d;
+}
+#endif
+#if defined(L_floatditf) && LIBGCC2_HAS_TF_MODE
TFtype
__floatditf (DWtype u)
{
- TFtype d = (Wtype) (u >> WORD_SIZE);
- d *= HIGH_HALFWORD_COEFF;
- d *= HIGH_HALFWORD_COEFF;
- d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
+#if W_TYPE_SIZE > TF_SIZE
+# error
+#endif
+ TFtype d = (Wtype) (u >> W_TYPE_SIZE);
+ d *= Wtype_MAXp1_F;
+ d += (UWtype)u;
+ return d;
+}
+#endif
+#if defined(L_floatunditf) && LIBGCC2_HAS_TF_MODE
+TFtype
+__floatunditf (UDWtype u)
+{
+#if W_TYPE_SIZE > TF_SIZE
+# error
+#endif
+ TFtype d = (UWtype) (u >> W_TYPE_SIZE);
+ d *= Wtype_MAXp1_F;
+ d += (UWtype)u;
return d;
}
#endif
-#ifdef L_floatdidf
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
+#if (defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE) \
+ || (defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE)
+#define DI_SIZE (W_TYPE_SIZE * 2)
+#define F_MODE_OK(SIZE) \
+ (SIZE < DI_SIZE \
+ && SIZE > (DI_SIZE - SIZE + FSSIZE) \
+ /* Don't use IBM Extended Double TFmode for TI->SF calculations. \
+ The conversion from long double to float suffers from double \
+ rounding, because we convert via double. In any case, the \
+ fallback code is faster. */ \
+ && !IS_IBM_EXTENDED (SIZE))
+#if defined(L_floatdisf)
+#define FUNC __floatdisf
+#define FSTYPE SFtype
+#define FSSIZE SF_SIZE
+#else
+#define FUNC __floatdidf
+#define FSTYPE DFtype
+#define FSSIZE DF_SIZE
+#endif
+
+FSTYPE
+FUNC (DWtype u)
+{
+#if FSSIZE >= W_TYPE_SIZE
+ /* When the word size is small, we never get any rounding error. */
+ FSTYPE f = (Wtype) (u >> W_TYPE_SIZE);
+ f *= Wtype_MAXp1_F;
+ f += (UWtype)u;
+ return f;
+#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \
+ || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \
+ || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
+
+#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE))
+# define FSIZE DF_SIZE
+# define FTYPE DFtype
+#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE))
+# define FSIZE XF_SIZE
+# define FTYPE XFtype
+#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
+# define FSIZE TF_SIZE
+# define FTYPE TFtype
+#else
+# error
+#endif
+
+#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE))
-DFtype
-__floatdidf (DWtype u)
-{
- DFtype d = (Wtype) (u >> WORD_SIZE);
- d *= HIGH_HALFWORD_COEFF;
- d *= HIGH_HALFWORD_COEFF;
- d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
+ /* Protect against double-rounding error.
+ Represent any low-order bits, that might be truncated by a bit that
+ won't be lost. The bit can go in anywhere below the rounding position
+ of the FSTYPE. A fixed mask and bit position handles all usual
+ configurations. */
+ if (! (- ((DWtype) 1 << FSIZE) < u
+ && u < ((DWtype) 1 << FSIZE)))
+ {
+ if ((UDWtype) u & (REP_BIT - 1))
+ {
+ u &= ~ (REP_BIT - 1);
+ u |= REP_BIT;
+ }
+ }
- return d;
+ /* Do the calculation in a wider type so that we don't lose any of
+ the precision of the high word while multiplying it. */
+ FTYPE f = (Wtype) (u >> W_TYPE_SIZE);
+ f *= Wtype_MAXp1_F;
+ f += (UWtype)u;
+ return (FSTYPE) f;
+#else
+#if FSSIZE >= W_TYPE_SIZE - 2
+# error
+#endif
+ /* Finally, the word size is larger than the number of bits in the
+ required FSTYPE, and we've got no suitable wider type. The only
+ way to avoid double rounding is to special case the
+ extraction. */
+
+ /* If there are no high bits set, fall back to one conversion. */
+ if ((Wtype)u == u)
+ return (FSTYPE)(Wtype)u;
+
+ /* Otherwise, find the power of two. */
+ Wtype hi = u >> W_TYPE_SIZE;
+ if (hi < 0)
+ hi = -hi;
+
+ UWtype count, shift;
+ count_leading_zeros (count, hi);
+
+ /* No leading bits means u == minimum. */
+ if (count == 0)
+ return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2));
+
+ shift = 1 + W_TYPE_SIZE - count;
+
+ /* Shift down the most significant bits. */
+ hi = u >> shift;
+
+ /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */
+ if (u & (((DWtype)1 << shift) - 1))
+ hi |= 1;
+
+ /* Convert the one word of data, and rescale. */
+ FSTYPE f = hi;
+ f *= (UDWtype)1 << shift;
+ return f;
+#endif
}
#endif
-#ifdef L_floatdisf
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
+#if (defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE) \
+ || (defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE)
+#define DI_SIZE (W_TYPE_SIZE * 2)
+#define F_MODE_OK(SIZE) \
+ (SIZE < DI_SIZE \
+ && SIZE > (DI_SIZE - SIZE + FSSIZE) \
+ /* Don't use IBM Extended Double TFmode for TI->SF calculations. \
+ The conversion from long double to float suffers from double \
+ rounding, because we convert via double. In any case, the \
+ fallback code is faster. */ \
+ && !IS_IBM_EXTENDED (SIZE))
+#if defined(L_floatundisf)
+#define FUNC __floatundisf
+#define FSTYPE SFtype
+#define FSSIZE SF_SIZE
+#else
+#define FUNC __floatundidf
+#define FSTYPE DFtype
+#define FSSIZE DF_SIZE
+#endif
+
+FSTYPE
+FUNC (UDWtype u)
+{
+#if FSSIZE >= W_TYPE_SIZE
+ /* When the word size is small, we never get any rounding error. */
+ FSTYPE f = (UWtype) (u >> W_TYPE_SIZE);
+ f *= Wtype_MAXp1_F;
+ f += (UWtype)u;
+ return f;
+#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \
+ || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \
+ || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
+
+#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE))
+# define FSIZE DF_SIZE
+# define FTYPE DFtype
+#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE))
+# define FSIZE XF_SIZE
+# define FTYPE XFtype
+#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
+# define FSIZE TF_SIZE
+# define FTYPE TFtype
+#else
+# error
+#endif
-#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
-#define DF_SIZE DBL_MANT_DIG
-#define SF_SIZE FLT_MANT_DIG
+#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE))
-SFtype
-__floatdisf (DWtype u)
-{
/* Protect against double-rounding error.
- Represent any low-order bits, that might be truncated in DFmode,
- by a bit that won't be lost. The bit can go in anywhere below the
- rounding position of the SFmode. A fixed mask and bit position
- handles all usual configurations. It doesn't handle the case
- of 128-bit DImode, however. */
- if (DF_SIZE < DI_SIZE
- && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
+ Represent any low-order bits, that might be truncated by a bit that
+ won't be lost. The bit can go in anywhere below the rounding position
+ of the FSTYPE. A fixed mask and bit position handles all usual
+ configurations. */
+ if (u >= ((UDWtype) 1 << FSIZE))
{
-#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
- if (! (- ((DWtype) 1 << DF_SIZE) < u
- && u < ((DWtype) 1 << DF_SIZE)))
+ if ((UDWtype) u & (REP_BIT - 1))
{
- if ((UDWtype) u & (REP_BIT - 1))
- {
- u &= ~ (REP_BIT - 1);
- u |= REP_BIT;
- }
+ u &= ~ (REP_BIT - 1);
+ u |= REP_BIT;
}
}
- /* Do the calculation in DFmode
- so that we don't lose any of the precision of the high word
- while multiplying it. */
- DFtype f = (Wtype) (u >> WORD_SIZE);
- f *= HIGH_HALFWORD_COEFF;
- f *= HIGH_HALFWORD_COEFF;
- f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
- return (SFtype) f;
+ /* Do the calculation in a wider type so that we don't lose any of
+ the precision of the high word while multiplying it. */
+ FTYPE f = (UWtype) (u >> W_TYPE_SIZE);
+ f *= Wtype_MAXp1_F;
+ f += (UWtype)u;
+ return (FSTYPE) f;
+#else
+#if FSSIZE == W_TYPE_SIZE - 1
+# error
+#endif
+ /* Finally, the word size is larger than the number of bits in the
+ required FSTYPE, and we've got no suitable wider type. The only
+ way to avoid double rounding is to special case the
+ extraction. */
+
+ /* If there are no high bits set, fall back to one conversion. */
+ if ((UWtype)u == u)
+ return (FSTYPE)(UWtype)u;
+
+ /* Otherwise, find the power of two. */
+ UWtype hi = u >> W_TYPE_SIZE;
+
+ UWtype count, shift;
+ count_leading_zeros (count, hi);
+
+ shift = W_TYPE_SIZE - count;
+
+ /* Shift down the most significant bits. */
+ hi = u >> shift;
+
+ /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */
+ if (u & (((UDWtype)1 << shift) - 1))
+ hi |= 1;
+
+ /* Convert the one word of data, and rescale. */
+ FSTYPE f = hi;
+ f *= (UDWtype)1 << shift;
+ return f;
+#endif
}
#endif
-#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
+#if defined(L_fixunsxfsi) && LIBGCC2_HAS_XF_MODE
/* Reenable the normal types, in case limits.h needs them. */
#undef char
#undef short
@@ -1431,7 +1629,7 @@ __fixunsxfSI (XFtype a)
}
#endif
-#ifdef L_fixunsdfsi
+#if defined(L_fixunsdfsi) && LIBGCC2_HAS_DF_MODE
/* Reenable the normal types, in case limits.h needs them. */
#undef char
#undef short
@@ -1453,7 +1651,7 @@ __fixunsdfSI (DFtype a)
}
#endif
-#ifdef L_fixunssfsi
+#if defined(L_fixunssfsi) && LIBGCC2_HAS_SF_MODE
/* Reenable the normal types, in case limits.h needs them. */
#undef char
#undef short
@@ -1475,6 +1673,245 @@ __fixunssfSI (SFtype a)
}
#endif
+/* Integer power helper used from __builtin_powi for non-constant
+ exponents. */
+
+#if (defined(L_powisf2) && LIBGCC2_HAS_SF_MODE) \
+ || (defined(L_powidf2) && LIBGCC2_HAS_DF_MODE) \
+ || (defined(L_powixf2) && LIBGCC2_HAS_XF_MODE) \
+ || (defined(L_powitf2) && LIBGCC2_HAS_TF_MODE)
+# if defined(L_powisf2)
+# define TYPE SFtype
+# define NAME __powisf2
+# elif defined(L_powidf2)
+# define TYPE DFtype
+# define NAME __powidf2
+# elif defined(L_powixf2)
+# define TYPE XFtype
+# define NAME __powixf2
+# elif defined(L_powitf2)
+# define TYPE TFtype
+# define NAME __powitf2
+# endif
+
+#undef int
+#undef unsigned
+TYPE
+NAME (TYPE x, int m)
+{
+ unsigned int n = m < 0 ? -m : m;
+ TYPE y = n % 2 ? x : 1;
+ while (n >>= 1)
+ {
+ x = x * x;
+ if (n % 2)
+ y = y * x;
+ }
+ return m < 0 ? 1/y : y;
+}
+
+#endif
+
+#if ((defined(L_mulsc3) || defined(L_divsc3)) && LIBGCC2_HAS_SF_MODE) \
+ || ((defined(L_muldc3) || defined(L_divdc3)) && LIBGCC2_HAS_DF_MODE) \
+ || ((defined(L_mulxc3) || defined(L_divxc3)) && LIBGCC2_HAS_XF_MODE) \
+ || ((defined(L_multc3) || defined(L_divtc3)) && LIBGCC2_HAS_TF_MODE)
+
+#undef float
+#undef double
+#undef long
+
+#if defined(L_mulsc3) || defined(L_divsc3)
+# define MTYPE SFtype
+# define CTYPE SCtype
+# define MODE sc
+# define CEXT f
+# define NOTRUNC __FLT_EVAL_METHOD__ == 0
+#elif defined(L_muldc3) || defined(L_divdc3)
+# define MTYPE DFtype
+# define CTYPE DCtype
+# define MODE dc
+# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64
+# define CEXT l
+# define NOTRUNC 1
+# else
+# define CEXT
+# define NOTRUNC __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1
+# endif
+#elif defined(L_mulxc3) || defined(L_divxc3)
+# define MTYPE XFtype
+# define CTYPE XCtype
+# define MODE xc
+# define CEXT l
+# define NOTRUNC 1
+#elif defined(L_multc3) || defined(L_divtc3)
+# define MTYPE TFtype
+# define CTYPE TCtype
+# define MODE tc
+# define CEXT l
+# define NOTRUNC 1
+#else
+# error
+#endif
+
+#define CONCAT3(A,B,C) _CONCAT3(A,B,C)
+#define _CONCAT3(A,B,C) A##B##C
+
+#define CONCAT2(A,B) _CONCAT2(A,B)
+#define _CONCAT2(A,B) A##B
+
+/* All of these would be present in a full C99 implementation of <math.h>
+ and <complex.h>. Our problem is that only a few systems have such full
+ implementations. Further, libgcc_s.so isn't currently linked against
+ libm.so, and even for systems that do provide full C99, the extra overhead
+ of all programs using libgcc having to link against libm. So avoid it. */
+
+#define isnan(x) __builtin_expect ((x) != (x), 0)
+#define isfinite(x) __builtin_expect (!isnan((x) - (x)), 1)
+#define isinf(x) __builtin_expect (!isnan(x) & !isfinite(x), 0)
+
+#define INFINITY CONCAT2(__builtin_inf, CEXT) ()
+#define I 1i
+
+/* Helpers to make the following code slightly less gross. */
+#define COPYSIGN CONCAT2(__builtin_copysign, CEXT)
+#define FABS CONCAT2(__builtin_fabs, CEXT)
+
+/* Verify that MTYPE matches up with CEXT. */
+extern void *compile_type_assert[sizeof(INFINITY) == sizeof(MTYPE) ? 1 : -1];
+
+/* Ensure that we've lost any extra precision. */
+#if NOTRUNC
+# define TRUNC(x)
+#else
+# define TRUNC(x) __asm__ ("" : "=m"(x) : "m"(x))
+#endif
+
+#if defined(L_mulsc3) || defined(L_muldc3) \
+ || defined(L_mulxc3) || defined(L_multc3)
+
+CTYPE
+CONCAT3(__mul,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d)
+{
+ MTYPE ac, bd, ad, bc, x, y;
+
+ ac = a * c;
+ bd = b * d;
+ ad = a * d;
+ bc = b * c;
+
+ TRUNC (ac);
+ TRUNC (bd);
+ TRUNC (ad);
+ TRUNC (bc);
+
+ x = ac - bd;
+ y = ad + bc;
+
+ if (isnan (x) && isnan (y))
+ {
+ /* Recover infinities that computed as NaN + iNaN. */
+ _Bool recalc = 0;
+ if (isinf (a) || isinf (b))
+ {
+ /* z is infinite. "Box" the infinity and change NaNs in
+ the other factor to 0. */
+ a = COPYSIGN (isinf (a) ? 1 : 0, a);
+ b = COPYSIGN (isinf (b) ? 1 : 0, b);
+ if (isnan (c)) c = COPYSIGN (0, c);
+ if (isnan (d)) d = COPYSIGN (0, d);
+ recalc = 1;
+ }
+ if (isinf (c) || isinf (d))
+ {
+ /* w is infinite. "Box" the infinity and change NaNs in
+ the other factor to 0. */
+ c = COPYSIGN (isinf (c) ? 1 : 0, c);
+ d = COPYSIGN (isinf (d) ? 1 : 0, d);
+ if (isnan (a)) a = COPYSIGN (0, a);
+ if (isnan (b)) b = COPYSIGN (0, b);
+ recalc = 1;
+ }
+ if (!recalc
+ && (isinf (ac) || isinf (bd)
+ || isinf (ad) || isinf (bc)))
+ {
+ /* Recover infinities from overflow by changing NaNs to 0. */
+ if (isnan (a)) a = COPYSIGN (0, a);
+ if (isnan (b)) b = COPYSIGN (0, b);
+ if (isnan (c)) c = COPYSIGN (0, c);
+ if (isnan (d)) d = COPYSIGN (0, d);
+ recalc = 1;
+ }
+ if (recalc)
+ {
+ x = INFINITY * (a * c - b * d);
+ y = INFINITY * (a * d + b * c);
+ }
+ }
+
+ return x + I * y;
+}
+#endif /* complex multiply */
+
+#if defined(L_divsc3) || defined(L_divdc3) \
+ || defined(L_divxc3) || defined(L_divtc3)
+
+CTYPE
+CONCAT3(__div,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d)
+{
+ MTYPE denom, ratio, x, y;
+
+ /* ??? We can get better behavior from logarithmic scaling instead of
+ the division. But that would mean starting to link libgcc against
+ libm. We could implement something akin to ldexp/frexp as gcc builtins
+ fairly easily... */
+ if (FABS (c) < FABS (d))
+ {
+ ratio = c / d;
+ denom = (c * ratio) + d;
+ x = ((a * ratio) + b) / denom;
+ y = ((b * ratio) - a) / denom;
+ }
+ else
+ {
+ ratio = d / c;
+ denom = (d * ratio) + c;
+ x = ((b * ratio) + a) / denom;
+ y = (b - (a * ratio)) / denom;
+ }
+
+ /* Recover infinities and zeros that computed as NaN+iNaN; the only cases
+ are nonzero/zero, infinite/finite, and finite/infinite. */
+ if (isnan (x) && isnan (y))
+ {
+ if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b)))
+ {
+ x = COPYSIGN (INFINITY, c) * a;
+ y = COPYSIGN (INFINITY, c) * b;
+ }
+ else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d))
+ {
+ a = COPYSIGN (isinf (a) ? 1 : 0, a);
+ b = COPYSIGN (isinf (b) ? 1 : 0, b);
+ x = INFINITY * (a * c + b * d);
+ y = INFINITY * (b * c - a * d);
+ }
+ else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b))
+ {
+ c = COPYSIGN (isinf (c) ? 1 : 0, c);
+ d = COPYSIGN (isinf (d) ? 1 : 0, d);
+ x = 0.0 * (a * c + b * d);
+ y = 0.0 * (b * c - a * d);
+ }
+ }
+
+ return x + I * y;
+}
+#endif /* complex divide */
+
+#endif /* all complex float routines */
+
/* From here on down, the routines use normal data types. */
#define SItype bogus_type
@@ -1575,7 +2012,7 @@ __enable_execute_stack (void *addr __attribute__((__unused__)))
#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
-long
+int
getpagesize (void)
{
#ifdef _ALPHA_
@@ -1624,6 +2061,7 @@ TRANSFER_FROM_TRAMPOLINE
#ifdef L__main
#include "gbl-ctors.h"
+
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
@@ -1633,7 +2071,7 @@ TRANSFER_FROM_TRAMPOLINE
#define SYMBOL__MAIN __main
#endif
-#ifdef INIT_SECTION_ASM_OP
+#if defined (INIT_SECTION_ASM_OP) || defined (INIT_ARRAY_SECTION_ASM_OP)
#undef HAS_INIT_SECTION
#define HAS_INIT_SECTION
#endif
@@ -1746,4 +2184,4 @@ func_ptr __DTOR_LIST__[2];
#endif
#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
#endif /* L_ctors */
-
+#endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */
diff --git a/contrib/gcc/print-tree.c b/contrib/gcc/print-tree.c
index 2965d6e..57b07ac 100644
--- a/contrib/gcc/print-tree.c
+++ b/contrib/gcc/print-tree.c
@@ -1,6 +1,6 @@
/* Prints out tree in human readable form - GCC
Copyright (C) 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
@@ -28,6 +28,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "real.h"
#include "ggc.h"
#include "langhooks.h"
+#include "tree-iterator.h"
/* Define the hash table of nodes already seen.
Such nodes are not repeated; brief cross-references are used. */
@@ -49,19 +50,29 @@ static struct bucket **table;
void
debug_tree (tree node)
{
- table = xcalloc (HASH_SIZE, sizeof (struct bucket *));
+ table = XCNEWVEC (struct bucket *, HASH_SIZE);
print_node (stderr, "", node, 0);
free (table);
table = 0;
putc ('\n', stderr);
}
+/* Print PREFIX and ADDR to FILE. */
+void
+dump_addr (FILE *file, const char *prefix, void *addr)
+{
+ if (flag_dump_noaddr || flag_dump_unnumbered)
+ fprintf (file, "%s#", prefix);
+ else
+ fprintf (file, "%s%p", prefix, addr);
+}
+
/* Print a node in brief fashion, with just the code, address and name. */
void
print_node_brief (FILE *file, const char *prefix, tree node, int indent)
{
- char class;
+ enum tree_code_class class;
if (node == 0)
return;
@@ -72,15 +83,21 @@ print_node_brief (FILE *file, const char *prefix, tree node, int indent)
name if any. */
if (indent > 0)
fprintf (file, " ");
- fprintf (file, "%s <%s " HOST_PTR_PRINTF,
- prefix, tree_code_name[(int) TREE_CODE (node)], (char *) node);
+ fprintf (file, "%s <%s", prefix, tree_code_name[(int) TREE_CODE (node)]);
+ dump_addr (file, " ", node);
- if (class == 'd')
+ if (class == tcc_declaration)
{
if (DECL_NAME (node))
fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
+ else if (TREE_CODE (node) == LABEL_DECL
+ && LABEL_DECL_UID (node) != -1)
+ fprintf (file, " L." HOST_WIDE_INT_PRINT_DEC, LABEL_DECL_UID (node));
+ else
+ fprintf (file, " %c.%u", TREE_CODE (node) == CONST_DECL ? 'C' : 'D',
+ DECL_UID (node));
}
- else if (class == 't')
+ else if (class == tcc_type)
{
if (TYPE_NAME (node))
{
@@ -121,7 +138,7 @@ print_node_brief (FILE *file, const char *prefix, tree node, int indent)
d = TREE_REAL_CST (node);
if (REAL_VALUE_ISINF (d))
- fprintf (file, " Inf");
+ fprintf (file, REAL_VALUE_NEGATIVE (d) ? " -Inf" : " Inf");
else if (REAL_VALUE_ISNAN (d))
fprintf (file, " Nan");
else
@@ -156,15 +173,17 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
int hash;
struct bucket *b;
enum machine_mode mode;
- char class;
+ enum tree_code_class class;
int len;
- int first_rtl;
int i;
+ expanded_location xloc;
+ enum tree_code code;
if (node == 0)
return;
-
- class = TREE_CODE_CLASS (TREE_CODE (node));
+
+ code = TREE_CODE (node);
+ class = TREE_CODE_CLASS (code);
/* Don't get too deep in nesting. If the user wants to see deeper,
it is easy to use the address of a lowest-level node
@@ -176,7 +195,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
return;
}
- if (indent > 8 && (class == 't' || class == 'd'))
+ if (indent > 8 && (class == tcc_type || class == tcc_declaration))
{
print_node_brief (file, prefix, node, indent);
return;
@@ -200,7 +219,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
}
/* Add this node to the table. */
- b = xmalloc (sizeof (struct bucket));
+ b = XNEW (struct bucket);
b->node = node;
b->next = table[hash];
table[hash] = b;
@@ -209,16 +228,22 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
indent_to (file, indent);
/* Print the slot this node is in, and its code, and address. */
- fprintf (file, "%s <%s " HOST_PTR_PRINTF,
- prefix, tree_code_name[(int) TREE_CODE (node)], (void *) node);
+ fprintf (file, "%s <%s", prefix, tree_code_name[(int) TREE_CODE (node)]);
+ dump_addr (file, " ", node);
/* Print the name, if any. */
- if (class == 'd')
+ if (class == tcc_declaration)
{
if (DECL_NAME (node))
fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
+ else if (TREE_CODE (node) == LABEL_DECL
+ && LABEL_DECL_UID (node) != -1)
+ fprintf (file, " L." HOST_WIDE_INT_PRINT_DEC, LABEL_DECL_UID (node));
+ else
+ fprintf (file, " %c.%u", TREE_CODE (node) == CONST_DECL ? 'C' : 'D',
+ DECL_UID (node));
}
- else if (class == 't')
+ else if (class == tcc_type)
{
if (TYPE_NAME (node))
{
@@ -245,18 +270,22 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
indent_to (file, indent + 3);
}
- if (TREE_SIDE_EFFECTS (node))
+ if (!TYPE_P (node) && TREE_SIDE_EFFECTS (node))
fputs (" side-effects", file);
- if (TREE_READONLY (node))
+
+ if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node))
fputs (" readonly", file);
- if (TREE_CONSTANT (node))
+ if (!TYPE_P (node) && TREE_CONSTANT (node))
fputs (" constant", file);
+ else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
+ fputs (" sizes-gimplified", file);
+
+ if (TREE_INVARIANT (node))
+ fputs (" invariant", file);
if (TREE_ADDRESSABLE (node))
fputs (" addressable", file);
if (TREE_THIS_VOLATILE (node))
fputs (" volatile", file);
- if (TREE_UNSIGNED (node))
- fputs (" unsigned", file);
if (TREE_ASM_WRITTEN (node))
fputs (" asm_written", file);
if (TREE_USED (node))
@@ -273,6 +302,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
fputs (" static", file);
if (TREE_DEPRECATED (node))
fputs (" deprecated", file);
+ if (TREE_VISITED (node))
+ fputs (" visited", file);
if (TREE_LANG_FLAG_0 (node))
fputs (" tree_0", file);
if (TREE_LANG_FLAG_1 (node))
@@ -292,27 +323,32 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
switch (TREE_CODE_CLASS (TREE_CODE (node)))
{
- case 'd':
- mode = DECL_MODE (node);
-
- if (DECL_IGNORED_P (node))
- fputs (" ignored", file);
- if (DECL_ABSTRACT (node))
- fputs (" abstract", file);
- if (DECL_IN_SYSTEM_HEADER (node))
- fputs (" in_system_header", file);
- if (DECL_COMMON (node))
- fputs (" common", file);
- if (DECL_EXTERNAL (node))
- fputs (" external", file);
- if (DECL_WEAK (node))
- fputs (" weak", file);
- if (DECL_REGISTER (node) && TREE_CODE (node) != FIELD_DECL
+ case tcc_declaration:
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ if (DECL_UNSIGNED (node))
+ fputs (" unsigned", file);
+ if (DECL_IGNORED_P (node))
+ fputs (" ignored", file);
+ if (DECL_ABSTRACT (node))
+ fputs (" abstract", file);
+ if (DECL_EXTERNAL (node))
+ fputs (" external", file);
+ if (DECL_NONLOCAL (node))
+ fputs (" nonlocal", file);
+ }
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+ {
+ if (DECL_WEAK (node))
+ fputs (" weak", file);
+ if (DECL_IN_SYSTEM_HEADER (node))
+ fputs (" in_system_header", file);
+ }
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL)
+ && TREE_CODE (node) != LABEL_DECL
&& TREE_CODE (node) != FUNCTION_DECL
- && TREE_CODE (node) != LABEL_DECL)
+ && DECL_REGISTER (node))
fputs (" regdecl", file);
- if (DECL_NONLOCAL (node))
- fputs (" nonlocal", file);
if (TREE_CODE (node) == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
fputs (" suppress-debug", file);
@@ -331,94 +367,132 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (TREE_CODE (node) == FIELD_DECL && DECL_NONADDRESSABLE_P (node))
fputs (" nonaddressable", file);
- if (TREE_CODE (node) == LABEL_DECL && DECL_TOO_LATE (node))
- fputs (" too-late", file);
if (TREE_CODE (node) == LABEL_DECL && DECL_ERROR_ISSUED (node))
fputs (" error-issued", file);
if (TREE_CODE (node) == VAR_DECL && DECL_IN_TEXT_SECTION (node))
fputs (" in-text-section", file);
- if (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node))
- fputs (" thread-local", file);
+ if (TREE_CODE (node) == VAR_DECL && DECL_COMMON (node))
+ fputs (" common", file);
+ if (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL_P (node))
+ {
+ enum tls_model kind = DECL_TLS_MODEL (node);
+ switch (kind)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ fputs (" tls-global-dynamic", file);
+ break;
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ fputs (" tls-local-dynamic", file);
+ break;
+ case TLS_MODEL_INITIAL_EXEC:
+ fputs (" tls-initial-exec", file);
+ break;
+ case TLS_MODEL_LOCAL_EXEC:
+ fputs (" tls-local-exec", file);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
- if (TREE_CODE (node) == PARM_DECL && DECL_TRANSPARENT_UNION (node))
- fputs (" transparent-union", file);
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ if (DECL_VIRTUAL_P (node))
+ fputs (" virtual", file);
+ if (DECL_PRESERVE_P (node))
+ fputs (" preserve", file);
+ if (DECL_LANG_FLAG_0 (node))
+ fputs (" decl_0", file);
+ if (DECL_LANG_FLAG_1 (node))
+ fputs (" decl_1", file);
+ if (DECL_LANG_FLAG_2 (node))
+ fputs (" decl_2", file);
+ if (DECL_LANG_FLAG_3 (node))
+ fputs (" decl_3", file);
+ if (DECL_LANG_FLAG_4 (node))
+ fputs (" decl_4", file);
+ if (DECL_LANG_FLAG_5 (node))
+ fputs (" decl_5", file);
+ if (DECL_LANG_FLAG_6 (node))
+ fputs (" decl_6", file);
+ if (DECL_LANG_FLAG_7 (node))
+ fputs (" decl_7", file);
+
+ mode = DECL_MODE (node);
+ fprintf (file, " %s", GET_MODE_NAME (mode));
+ }
- if (DECL_VIRTUAL_P (node))
- fputs (" virtual", file);
- if (DECL_DEFER_OUTPUT (node))
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS) && DECL_DEFER_OUTPUT (node))
fputs (" defer-output", file);
- if (DECL_LANG_FLAG_0 (node))
- fputs (" decl_0", file);
- if (DECL_LANG_FLAG_1 (node))
- fputs (" decl_1", file);
- if (DECL_LANG_FLAG_2 (node))
- fputs (" decl_2", file);
- if (DECL_LANG_FLAG_3 (node))
- fputs (" decl_3", file);
- if (DECL_LANG_FLAG_4 (node))
- fputs (" decl_4", file);
- if (DECL_LANG_FLAG_5 (node))
- fputs (" decl_5", file);
- if (DECL_LANG_FLAG_6 (node))
- fputs (" decl_6", file);
- if (DECL_LANG_FLAG_7 (node))
- fputs (" decl_7", file);
-
- fprintf (file, " %s", GET_MODE_NAME (mode));
- fprintf (file, " file %s line %d",
- DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node));
-
- print_node (file, "size", DECL_SIZE (node), indent + 4);
- print_node (file, "unit size", DECL_SIZE_UNIT (node), indent + 4);
- if (TREE_CODE (node) != FUNCTION_DECL
- || DECL_INLINE (node) || DECL_BUILT_IN (node))
- indent_to (file, indent + 3);
+ xloc = expand_location (DECL_SOURCE_LOCATION (node));
+ fprintf (file, " file %s line %d", xloc.file, xloc.line);
- if (TREE_CODE (node) != FUNCTION_DECL)
- {
- if (DECL_USER_ALIGN (node))
- fprintf (file, " user");
-
- fprintf (file, " align %d", DECL_ALIGN (node));
- if (TREE_CODE (node) == FIELD_DECL)
- fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED,
- DECL_OFFSET_ALIGN (node));
- }
- else if (DECL_BUILT_IN (node))
- {
- if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD)
- fprintf (file, " built-in BUILT_IN_MD %d", DECL_FUNCTION_CODE (node));
- else
- fprintf (file, " built-in %s:%s",
- built_in_class_names[(int) DECL_BUILT_IN_CLASS (node)],
- built_in_names[(int) DECL_FUNCTION_CODE (node)]);
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ print_node (file, "size", DECL_SIZE (node), indent + 4);
+ print_node (file, "unit size", DECL_SIZE_UNIT (node), indent + 4);
+
+ if (TREE_CODE (node) != FUNCTION_DECL
+ || DECL_INLINE (node) || DECL_BUILT_IN (node))
+ indent_to (file, indent + 3);
+
+ if (TREE_CODE (node) != FUNCTION_DECL)
+ {
+ if (DECL_USER_ALIGN (node))
+ fprintf (file, " user");
+
+ fprintf (file, " align %d", DECL_ALIGN (node));
+ if (TREE_CODE (node) == FIELD_DECL)
+ fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED,
+ DECL_OFFSET_ALIGN (node));
+ }
+ else if (DECL_BUILT_IN (node))
+ {
+ if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD)
+ fprintf (file, " built-in BUILT_IN_MD %d", DECL_FUNCTION_CODE (node));
+ else
+ fprintf (file, " built-in %s:%s",
+ built_in_class_names[(int) DECL_BUILT_IN_CLASS (node)],
+ built_in_names[(int) DECL_FUNCTION_CODE (node)]);
+ }
+
+ if (DECL_POINTER_ALIAS_SET_KNOWN_P (node))
+ fprintf (file, " alias set " HOST_WIDE_INT_PRINT_DEC,
+ DECL_POINTER_ALIAS_SET (node));
}
-
- if (DECL_POINTER_ALIAS_SET_KNOWN_P (node))
- fprintf (file, " alias set " HOST_WIDE_INT_PRINT_DEC,
- DECL_POINTER_ALIAS_SET (node));
-
if (TREE_CODE (node) == FIELD_DECL)
{
print_node (file, "offset", DECL_FIELD_OFFSET (node), indent + 4);
print_node (file, "bit offset", DECL_FIELD_BIT_OFFSET (node),
indent + 4);
+ if (DECL_BIT_FIELD_TYPE (node))
+ print_node (file, "bit_field_type", DECL_BIT_FIELD_TYPE (node),
+ indent + 4);
}
print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
- print_node_brief (file, "attributes",
- DECL_ATTRIBUTES (node), indent + 4);
- print_node_brief (file, "abstract_origin",
- DECL_ABSTRACT_ORIGIN (node), indent + 4);
- print_node (file, "arguments", DECL_ARGUMENTS (node), indent + 4);
- print_node (file, "result", DECL_RESULT_FLD (node), indent + 4);
- print_node_brief (file, "initial", DECL_INITIAL (node), indent + 4);
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+ {
+ print_node_brief (file, "attributes",
+ DECL_ATTRIBUTES (node), indent + 4);
+ print_node_brief (file, "initial", DECL_INITIAL (node), indent + 4);
+ }
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL))
+ {
+ print_node_brief (file, "abstract_origin",
+ DECL_ABSTRACT_ORIGIN (node), indent + 4);
+ }
+ if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
+ {
+ print_node (file, "arguments", DECL_ARGUMENT_FLD (node), indent + 4);
+ print_node (file, "result", DECL_RESULT_FLD (node), indent + 4);
+ }
- (*lang_hooks.print_decl) (file, node, indent);
+ lang_hooks.print_decl (file, node, indent);
if (DECL_RTL_SET_P (node))
{
@@ -429,8 +503,6 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (TREE_CODE (node) == PARM_DECL)
{
print_node (file, "arg-type", DECL_ARG_TYPE (node), indent + 4);
- print_node (file, "arg-type-as-written",
- DECL_ARG_TYPE_AS_WRITTEN (node), indent + 4);
if (DECL_INCOMING_RTL (node) != 0)
{
@@ -440,13 +512,25 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
}
}
else if (TREE_CODE (node) == FUNCTION_DECL
- && DECL_SAVED_INSNS (node) != 0)
+ && DECL_STRUCT_FUNCTION (node) != 0)
{
indent_to (file, indent + 4);
- fprintf (file, "saved-insns " HOST_PTR_PRINTF,
- (void *) DECL_SAVED_INSNS (node));
+ dump_addr (file, "saved-insns ", DECL_STRUCT_FUNCTION (node));
}
+ if ((TREE_CODE (node) == VAR_DECL || TREE_CODE (node) == PARM_DECL)
+ && DECL_HAS_VALUE_EXPR_P (node))
+ print_node (file, "value-expr", DECL_VALUE_EXPR (node), indent + 4);
+
+ if (TREE_CODE (node) == STRUCT_FIELD_TAG)
+ {
+ fprintf (file, " sft size " HOST_WIDE_INT_PRINT_DEC,
+ SFT_SIZE (node));
+ fprintf (file, " sft offset " HOST_WIDE_INT_PRINT_DEC,
+ SFT_OFFSET (node));
+ print_node_brief (file, "parent var", SFT_PARENT_VAR (node),
+ indent + 4);
+ }
/* Print the decl chain only if decl is at second level. */
if (indent == 4)
print_node (file, "chain", TREE_CHAIN (node), indent + 4);
@@ -454,7 +538,10 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
break;
- case 't':
+ case tcc_type:
+ if (TYPE_UNSIGNED (node))
+ fputs (" unsigned", file);
+
/* The no-force-blk flag is used for different things in
different types. */
if ((TREE_CODE (node) == RECORD_TYPE
@@ -528,8 +615,10 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (TREE_CODE (node) == ENUMERAL_TYPE)
print_node (file, "values", TYPE_VALUES (node), indent + 4);
- else if (TREE_CODE (node) == ARRAY_TYPE || TREE_CODE (node) == SET_TYPE)
+ else if (TREE_CODE (node) == ARRAY_TYPE)
print_node (file, "domain", TYPE_DOMAIN (node), indent + 4);
+ else if (TREE_CODE (node) == VECTOR_TYPE)
+ fprintf (file, " nunits %d", (int) TYPE_VECTOR_SUBPARTS (node));
else if (TREE_CODE (node) == RECORD_TYPE
|| TREE_CODE (node) == UNION_TYPE
|| TREE_CODE (node) == QUAL_UNION_TYPE)
@@ -549,7 +638,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (TYPE_CONTEXT (node))
print_node_brief (file, "context", TYPE_CONTEXT (node), indent + 4);
- (*lang_hooks.print_type) (file, node, indent);
+ lang_hooks.print_type (file, node, indent);
if (TYPE_POINTER_TO (node) || TREE_CHAIN (node))
indent_to (file, indent + 3);
@@ -561,21 +650,14 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
break;
- case 'b':
- print_node (file, "vars", BLOCK_VARS (node), indent + 4);
- print_node (file, "supercontext", BLOCK_SUPERCONTEXT (node), indent + 4);
- print_node (file, "subblocks", BLOCK_SUBBLOCKS (node), indent + 4);
- print_node (file, "chain", BLOCK_CHAIN (node), indent + 4);
- print_node (file, "abstract_origin",
- BLOCK_ABSTRACT_ORIGIN (node), indent + 4);
- break;
-
- case 'e':
- case '<':
- case '1':
- case '2':
- case 'r':
- case 's':
+ case tcc_expression:
+ case tcc_comparison:
+ case tcc_unary:
+ case tcc_binary:
+ case tcc_reference:
+ case tcc_statement:
+ if (TREE_CODE (node) == BIT_FIELD_REF && BIT_FIELD_REF_UNSIGNED (node))
+ fputs (" unsigned", file);
if (TREE_CODE (node) == BIND_EXPR)
{
print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4);
@@ -586,44 +668,19 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
len = TREE_CODE_LENGTH (TREE_CODE (node));
- /* Some nodes contain rtx's, not trees,
- after a certain point. Print the rtx's as rtx's. */
- first_rtl = first_rtl_op (TREE_CODE (node));
-
for (i = 0; i < len; i++)
{
- if (i >= first_rtl)
- {
- indent_to (file, indent + 4);
- fprintf (file, "rtl %d ", i);
- if (TREE_OPERAND (node, i))
- print_rtl (file, (rtx) TREE_OPERAND (node, i));
- else
- fprintf (file, "(nil)");
- fprintf (file, "\n");
- }
- else
- {
- char temp[10];
+ char temp[10];
- sprintf (temp, "arg %d", i);
- print_node (file, temp, TREE_OPERAND (node, i), indent + 4);
- }
+ sprintf (temp, "arg %d", i);
+ print_node (file, temp, TREE_OPERAND (node, i), indent + 4);
}
- if (TREE_CODE (node) == EXPR_WITH_FILE_LOCATION)
- {
- indent_to (file, indent+4);
- fprintf (file, "%s:%d:%d",
- (EXPR_WFL_FILENAME_NODE (node ) ?
- EXPR_WFL_FILENAME (node) : "(no file info)"),
- EXPR_WFL_LINENO (node), EXPR_WFL_COLNO (node));
- }
print_node (file, "chain", TREE_CHAIN (node), indent + 4);
break;
- case 'c':
- case 'x':
+ case tcc_constant:
+ case tcc_exceptional:
switch (TREE_CODE (node))
{
case INTEGER_CST:
@@ -652,7 +709,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
d = TREE_REAL_CST (node);
if (REAL_VALUE_ISINF (d))
- fprintf (file, " Inf");
+ fprintf (file, REAL_VALUE_NEGATIVE (d) ? " -Inf" : " Inf");
else if (REAL_VALUE_ISNAN (d))
fprintf (file, " Nan");
else
@@ -708,7 +765,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
break;
case IDENTIFIER_NODE:
- (*lang_hooks.print_identifier) (file, node, indent);
+ lang_hooks.print_identifier (file, node, indent);
break;
case TREE_LIST:
@@ -729,14 +786,91 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
}
break;
+ case STATEMENT_LIST:
+ dump_addr (file, " head ", node->stmt_list.head);
+ dump_addr (file, " tail ", node->stmt_list.tail);
+ fprintf (file, " stmts");
+ {
+ tree_stmt_iterator i;
+ for (i = tsi_start (node); !tsi_end_p (i); tsi_next (&i))
+ {
+ /* Not printing the addresses of the (not-a-tree)
+ 'struct tree_stmt_list_node's. */
+ dump_addr (file, " ", tsi_stmt (i));
+ }
+ fprintf (file, "\n");
+ for (i = tsi_start (node); !tsi_end_p (i); tsi_next (&i))
+ {
+ /* Not printing the addresses of the (not-a-tree)
+ 'struct tree_stmt_list_node's. */
+ print_node (file, "stmt", tsi_stmt (i), indent + 4);
+ }
+ }
+ print_node (file, "chain", TREE_CHAIN (node), indent + 4);
+ break;
+
+ case BLOCK:
+ print_node (file, "vars", BLOCK_VARS (node), indent + 4);
+ print_node (file, "supercontext", BLOCK_SUPERCONTEXT (node),
+ indent + 4);
+ print_node (file, "subblocks", BLOCK_SUBBLOCKS (node), indent + 4);
+ print_node (file, "chain", BLOCK_CHAIN (node), indent + 4);
+ print_node (file, "abstract_origin",
+ BLOCK_ABSTRACT_ORIGIN (node), indent + 4);
+ break;
+
+ case SSA_NAME:
+ print_node_brief (file, "var", SSA_NAME_VAR (node), indent + 4);
+ print_node_brief (file, "def_stmt",
+ SSA_NAME_DEF_STMT (node), indent + 4);
+
+ indent_to (file, indent + 4);
+ fprintf (file, "version %u", SSA_NAME_VERSION (node));
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (node))
+ fprintf (file, " in-abnormal-phi");
+ if (SSA_NAME_IN_FREE_LIST (node))
+ fprintf (file, " in-free-list");
+
+ if (SSA_NAME_PTR_INFO (node)
+ || SSA_NAME_VALUE (node))
+ {
+ indent_to (file, indent + 3);
+ if (SSA_NAME_PTR_INFO (node))
+ dump_addr (file, " ptr-info ", SSA_NAME_PTR_INFO (node));
+ if (SSA_NAME_VALUE (node))
+ dump_addr (file, " value ", SSA_NAME_VALUE (node));
+ }
+ break;
+
+ case OMP_CLAUSE:
+ {
+ int i;
+ fprintf (file, " %s",
+ omp_clause_code_name[OMP_CLAUSE_CODE (node)]);
+ for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (node)]; i++)
+ {
+ indent_to (file, indent + 4);
+ fprintf (file, "op %d:", i);
+ print_node_brief (file, "", OMP_CLAUSE_OPERAND (node, i), 0);
+ }
+ }
+ break;
+
default:
- if (TREE_CODE_CLASS (TREE_CODE (node)) == 'x')
- (*lang_hooks.print_xnode) (file, node, indent);
+ if (EXCEPTIONAL_CLASS_P (node))
+ lang_hooks.print_xnode (file, node, indent);
break;
}
break;
}
+ if (EXPR_HAS_LOCATION (node))
+ {
+ expanded_location xloc = expand_location (EXPR_LOCATION (node));
+ indent_to (file, indent+4);
+ fprintf (file, "%s:%d", xloc.file, xloc.line);
+ }
+
fprintf (file, ">");
}
diff --git a/contrib/gcc/recog.c b/contrib/gcc/recog.c
index 2224c5a..cd1cb7d 100644
--- a/contrib/gcc/recog.c
+++ b/contrib/gcc/recog.c
@@ -1,6 +1,6 @@
/* Subroutines used by or related to instruction recognition.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "hard-reg-set.h"
#include "recog.h"
#include "regs.h"
+#include "addresses.h"
#include "expr.h"
#include "function.h"
#include "flags.h"
@@ -39,6 +40,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "basic-block.h"
#include "output.h"
#include "reload.h"
+#include "timevar.h"
+#include "tree-pass.h"
#ifndef STACK_PUSH_CODE
#ifdef STACK_GROWS_DOWNWARD
@@ -107,22 +110,6 @@ init_recog (void)
volatile_ok = 1;
}
-/* Try recognizing the instruction INSN,
- and return the code number that results.
- Remember the code so that repeated calls do not
- need to spend the time for actual rerecognition.
-
- This function is the normal interface to instruction recognition.
- The automatically-generated function `recog' is normally called
- through this one. (The only exception is in combine.c.) */
-
-int
-recog_memoized_1 (rtx insn)
-{
- if (INSN_CODE (insn) < 0)
- INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
- return INSN_CODE (insn);
-}
/* Check that X is an insn-body for an `asm' with operands
and that the operands mentioned in it are legitimate. */
@@ -211,8 +198,7 @@ validate_change (rtx object, rtx *loc, rtx new, int in_group)
if (old == new || rtx_equal_p (old, new))
return 1;
- if (in_group == 0 && num_changes != 0)
- abort ();
+ gcc_assert (in_group != 0 || num_changes == 0);
*loc = new;
@@ -233,7 +219,7 @@ validate_change (rtx object, rtx *loc, rtx new, int in_group)
changes[num_changes].loc = loc;
changes[num_changes].old = old;
- if (object && GET_CODE (object) != MEM)
+ if (object && !MEM_P (object))
{
/* Set INSN_CODE to force rerecognition of insn. Save old code in
case invalid. */
@@ -252,6 +238,7 @@ validate_change (rtx object, rtx *loc, rtx new, int in_group)
return apply_change_group ();
}
+
/* This subroutine of apply_change_group verifies whether the changes to INSN
were valid; i.e. whether INSN can still be recognized. */
@@ -311,11 +298,11 @@ num_changes_pending (void)
return num_changes;
}
-/* Apply a group of changes previously issued with `validate_change'.
+/* Tentatively apply the changes numbered NUM and up.
Return 1 if all changes are valid, zero otherwise. */
int
-apply_change_group (void)
+verify_changes (int num)
{
int i;
rtx last_validated = NULL_RTX;
@@ -329,7 +316,7 @@ apply_change_group (void)
we also require that the operands meet the constraints for
the insn. */
- for (i = 0; i < num_changes; i++)
+ for (i = num; i < num_changes; i++)
{
rtx object = changes[i].object;
@@ -338,7 +325,7 @@ apply_change_group (void)
if (object == 0 || object == last_validated)
continue;
- if (GET_CODE (object) == MEM)
+ if (MEM_P (object))
{
if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
break;
@@ -393,17 +380,38 @@ apply_change_group (void)
last_validated = object;
}
- if (i == num_changes)
- {
- basic_block bb;
+ return (i == num_changes);
+}
+
+/* A group of changes has previously been issued with validate_change and
+ verified with verify_changes. Update the BB_DIRTY flags of the affected
+ blocks, and clear num_changes. */
+
+void
+confirm_change_group (void)
+{
+ int i;
+ basic_block bb;
+
+ for (i = 0; i < num_changes; i++)
+ if (changes[i].object
+ && INSN_P (changes[i].object)
+ && (bb = BLOCK_FOR_INSN (changes[i].object)))
+ bb->flags |= BB_DIRTY;
+
+ num_changes = 0;
+}
- for (i = 0; i < num_changes; i++)
- if (changes[i].object
- && INSN_P (changes[i].object)
- && (bb = BLOCK_FOR_INSN (changes[i].object)))
- bb->flags |= BB_DIRTY;
+/* Apply a group of changes previously issued with `validate_change'.
+ If all changes are valid, call confirm_change_group and return 1,
+ otherwise, call cancel_changes and return 0. */
- num_changes = 0;
+int
+apply_change_group (void)
+{
+ if (verify_changes (0))
+ {
+ confirm_change_group ();
return 1;
}
else
@@ -413,6 +421,7 @@ apply_change_group (void)
}
}
+
/* Return the number of changes so far in the current group. */
int
@@ -433,7 +442,7 @@ cancel_changes (int num)
for (i = num_changes - 1; i >= num; i--)
{
*changes[i].loc = changes[i].old;
- if (changes[i].object && GET_CODE (changes[i].object) != MEM)
+ if (changes[i].object && !MEM_P (changes[i].object))
INSN_CODE (changes[i].object) = changes[i].old_code;
}
num_changes = num;
@@ -466,7 +475,7 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
operands look similar. */
if (x == from
- || (GET_CODE (x) == REG && GET_CODE (from) == REG
+ || (REG_P (x) && REG_P (from)
&& GET_MODE (x) == GET_MODE (from)
&& REGNO (x) == REGNO (from))
|| (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
@@ -489,9 +498,9 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
&& GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
{
/* Verify that operands are really shared. */
- if (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0))) !=
- ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, j))))
- abort ();
+ gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
+ == ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
+ (x, 0, j))));
validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
from, to, object);
}
@@ -521,11 +530,11 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
/* Do changes needed to keep rtx consistent. Don't do any other
simplifications, as it is not our job. */
- if ((GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == 'c')
+ if (SWAPPABLE_OPERANDS_P (x)
&& swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
{
validate_change (object, loc,
- gen_rtx_fmt_ee (GET_RTX_CLASS (code) == 'c' ? code
+ gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code
: swap_condition (code),
GET_MODE (x), XEXP (x, 1),
XEXP (x, 0)), 1);
@@ -586,7 +595,7 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
likely to be an insertion operation; if it was, nothing bad will
happen, we might just fail in some cases). */
- if (GET_CODE (XEXP (x, 0)) == MEM
+ if (MEM_P (XEXP (x, 0))
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& GET_CODE (XEXP (x, 2)) == CONST_INT
&& !mode_dependent_address_p (XEXP (XEXP (x, 0), 0))
@@ -641,17 +650,6 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
}
}
-/* Try replacing every occurrence of FROM in subexpression LOC of INSN
- with TO. After all changes have been made, validate by seeing
- if INSN is still valid. */
-
-int
-validate_replace_rtx_subexp (rtx from, rtx to, rtx insn, rtx *loc)
-{
- validate_replace_rtx_1 (loc, from, to, insn);
- return apply_change_group ();
-}
-
/* Try replacing every occurrence of FROM in INSN with TO. After all
changes have been made, validate by seeing if INSN is still valid. */
@@ -701,13 +699,44 @@ validate_replace_src_group (rtx from, rtx to, rtx insn)
note_uses (&PATTERN (insn), validate_replace_src_1, &d);
}
-/* Same as validate_replace_src_group, but validate by seeing if
- INSN is still valid. */
-int
-validate_replace_src (rtx from, rtx to, rtx insn)
+/* Try simplify INSN.
+ Invoke simplify_rtx () on every SET_SRC and SET_DEST inside the INSN's
+ pattern and return true if something was simplified. */
+
+bool
+validate_simplify_insn (rtx insn)
{
- validate_replace_src_group (from, to, insn);
- return apply_change_group ();
+ int i;
+ rtx pat = NULL;
+ rtx newpat = NULL;
+
+ pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == SET)
+ {
+ newpat = simplify_rtx (SET_SRC (pat));
+ if (newpat && !rtx_equal_p (SET_SRC (pat), newpat))
+ validate_change (insn, &SET_SRC (pat), newpat, 1);
+ newpat = simplify_rtx (SET_DEST (pat));
+ if (newpat && !rtx_equal_p (SET_DEST (pat), newpat))
+ validate_change (insn, &SET_DEST (pat), newpat, 1);
+ }
+ else if (GET_CODE (pat) == PARALLEL)
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx s = XVECEXP (pat, 0, i);
+
+ if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
+ {
+ newpat = simplify_rtx (SET_SRC (s));
+ if (newpat && !rtx_equal_p (SET_SRC (s), newpat))
+ validate_change (insn, &SET_SRC (s), newpat, 1);
+ newpat = simplify_rtx (SET_DEST (s));
+ if (newpat && !rtx_equal_p (SET_DEST (s), newpat))
+ validate_change (insn, &SET_DEST (s), newpat, 1);
+ }
+ }
+ return ((num_changes_pending () > 0) && (apply_change_group () > 0));
}
#ifdef HAVE_cc0
@@ -724,9 +753,7 @@ next_insn_tests_no_inequality (rtx insn)
if (next == 0)
return 0;
- return ((GET_CODE (next) == JUMP_INSN
- || GET_CODE (next) == INSN
- || GET_CODE (next) == CALL_INSN)
+ return (INSN_P (next)
&& ! inequality_comparisons_p (PATTERN (next)));
}
#endif
@@ -764,9 +791,9 @@ find_single_use_1 (rtx dest, rtx *loc)
need just check the source. */
if (GET_CODE (SET_DEST (x)) != CC0
&& GET_CODE (SET_DEST (x)) != PC
- && GET_CODE (SET_DEST (x)) != REG
+ && !REG_P (SET_DEST (x))
&& ! (GET_CODE (SET_DEST (x)) == SUBREG
- && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
+ && REG_P (SUBREG_REG (SET_DEST (x)))
&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
@@ -792,7 +819,7 @@ find_single_use_1 (rtx dest, rtx *loc)
if (fmt[i] == 'e')
{
if (dest == XEXP (x, i)
- || (GET_CODE (dest) == REG && GET_CODE (XEXP (x, i)) == REG
+ || (REG_P (dest) && REG_P (XEXP (x, i))
&& REGNO (dest) == REGNO (XEXP (x, i))))
this_result = loc;
else
@@ -811,8 +838,8 @@ find_single_use_1 (rtx dest, rtx *loc)
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
{
if (XVECEXP (x, i, j) == dest
- || (GET_CODE (dest) == REG
- && GET_CODE (XVECEXP (x, i, j)) == REG
+ || (REG_P (dest)
+ && REG_P (XVECEXP (x, i, j))
&& REGNO (XVECEXP (x, i, j)) == REGNO (dest)))
this_result = loc;
else
@@ -859,7 +886,7 @@ find_single_use (rtx dest, rtx insn, rtx *ploc)
{
next = NEXT_INSN (insn);
if (next == 0
- || (GET_CODE (next) != INSN && GET_CODE (next) != JUMP_INSN))
+ || (!NONJUMP_INSN_P (next) && !JUMP_P (next)))
return 0;
result = find_single_use_1 (dest, &PATTERN (next));
@@ -869,11 +896,11 @@ find_single_use (rtx dest, rtx insn, rtx *ploc)
}
#endif
- if (reload_completed || reload_in_progress || GET_CODE (dest) != REG)
+ if (reload_completed || reload_in_progress || !REG_P (dest))
return 0;
for (next = next_nonnote_insn (insn);
- next != 0 && GET_CODE (next) != CODE_LABEL;
+ next != 0 && !LABEL_P (next);
next = next_nonnote_insn (next))
if (INSN_P (next) && dead_or_set_p (next, dest))
{
@@ -933,9 +960,7 @@ general_operand (rtx op, enum machine_mode mode)
if (CONSTANT_P (op))
return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
|| mode == VOIDmode)
-#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
-#endif
&& LEGITIMATE_CONSTANT_P (op));
/* Except for certain constants with VOIDmode, already checked for,
@@ -950,8 +975,10 @@ general_operand (rtx op, enum machine_mode mode)
#ifdef INSN_SCHEDULING
/* On machines that have insn scheduling, we want all memory
- reference to be explicit, so outlaw paradoxical SUBREGs. */
- if (GET_CODE (sub) == MEM
+ reference to be explicit, so outlaw paradoxical SUBREGs.
+ However, we must allow them after reload so that they can
+ get cleaned up by cleanup_subreg_operands. */
+ if (!reload_completed && MEM_P (sub)
&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub)))
return 0;
#endif
@@ -962,12 +989,12 @@ general_operand (rtx op, enum machine_mode mode)
??? This is a kludge. */
if (!reload_completed && SUBREG_BYTE (op) != 0
- && GET_CODE (sub) == MEM)
+ && MEM_P (sub))
return 0;
/* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally
create such rtl, and we must reject it. */
- if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
+ if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
&& GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
return 0;
@@ -987,23 +1014,12 @@ general_operand (rtx op, enum machine_mode mode)
if (! volatile_ok && MEM_VOLATILE_P (op))
return 0;
- if (GET_CODE (y) == ADDRESSOF)
- return 1;
-
/* Use the mem's mode, since it will be reloaded thus. */
- mode = GET_MODE (op);
- GO_IF_LEGITIMATE_ADDRESS (mode, y, win);
+ if (memory_address_p (GET_MODE (op), y))
+ return 1;
}
- /* Pretend this is an operand for now; we'll run force_operand
- on its replacement in fixup_var_refs_1. */
- if (code == ADDRESSOF)
- return 1;
-
return 0;
-
- win:
- return 1;
}
/* Return 1 if OP is a valid memory address for a memory reference
@@ -1048,11 +1064,11 @@ register_operand (rtx op, enum machine_mode mode)
(Ideally, (SUBREG (MEM)...) should not exist after reload,
but currently it does result from (SUBREG (REG)...) where the
reg went on the stack.) */
- if (! reload_completed && GET_CODE (sub) == MEM)
+ if (! reload_completed && MEM_P (sub))
return general_operand (op, mode);
#ifdef CANNOT_CHANGE_MODE_CLASS
- if (GET_CODE (sub) == REG
+ if (REG_P (sub)
&& REGNO (sub) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
@@ -1062,21 +1078,16 @@ register_operand (rtx op, enum machine_mode mode)
/* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally
create such rtl, and we must reject it. */
- if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
+ if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
&& GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
return 0;
op = sub;
}
- /* If we have an ADDRESSOF, consider it valid since it will be
- converted into something that will not be a MEM. */
- if (GET_CODE (op) == ADDRESSOF)
- return 1;
-
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
- return (GET_CODE (op) == REG
+ return (REG_P (op)
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
}
@@ -1099,7 +1110,7 @@ scratch_operand (rtx op, enum machine_mode mode)
return 0;
return (GET_CODE (op) == SCRATCH
- || (GET_CODE (op) == REG
+ || (REG_P (op)
&& REGNO (op) < FIRST_PSEUDO_REGISTER));
}
@@ -1123,18 +1134,10 @@ immediate_operand (rtx op, enum machine_mode mode)
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
- /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and
- result in 0/1. It seems a safe assumption that this is
- in range for everyone. */
- if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
-
return (CONSTANT_P (op)
&& (GET_MODE (op) == mode || mode == VOIDmode
|| GET_MODE (op) == VOIDmode)
-#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
-#endif
&& LEGITIMATE_CONSTANT_P (op));
}
@@ -1200,9 +1203,7 @@ nonmemory_operand (rtx op, enum machine_mode mode)
return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
|| mode == VOIDmode)
-#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
-#endif
&& LEGITIMATE_CONSTANT_P (op));
}
@@ -1217,14 +1218,14 @@ nonmemory_operand (rtx op, enum machine_mode mode)
(Ideally, (SUBREG (MEM)...) should not exist after reload,
but currently it does result from (SUBREG (REG)...) where the
reg went on the stack.) */
- if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM)
+ if (! reload_completed && MEM_P (SUBREG_REG (op)))
return general_operand (op, mode);
op = SUBREG_REG (op);
}
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
- return (GET_CODE (op) == REG
+ return (REG_P (op)
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
}
@@ -1244,7 +1245,7 @@ push_operand (rtx op, enum machine_mode mode)
rounded_size = PUSH_ROUNDING (rounded_size);
#endif
- if (GET_CODE (op) != MEM)
+ if (!MEM_P (op))
return 0;
if (mode != VOIDmode && GET_MODE (op) != mode)
@@ -1284,7 +1285,7 @@ push_operand (rtx op, enum machine_mode mode)
int
pop_operand (rtx op, enum machine_mode mode)
{
- if (GET_CODE (op) != MEM)
+ if (!MEM_P (op))
return 0;
if (mode != VOIDmode && GET_MODE (op) != mode)
@@ -1303,9 +1304,6 @@ pop_operand (rtx op, enum machine_mode mode)
int
memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
{
- if (GET_CODE (addr) == ADDRESSOF)
- return 1;
-
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
return 0;
@@ -1327,7 +1325,7 @@ memory_operand (rtx op, enum machine_mode mode)
if (! reload_completed)
/* Note that no SUBREG is a memory operand before end of reload pass,
because (SUBREG (MEM...)) forces reloading into a register. */
- return GET_CODE (op) == MEM && general_operand (op, mode);
+ return MEM_P (op) && general_operand (op, mode);
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
@@ -1336,7 +1334,7 @@ memory_operand (rtx op, enum machine_mode mode)
if (GET_CODE (inner) == SUBREG)
inner = SUBREG_REG (inner);
- return (GET_CODE (inner) == MEM && general_operand (op, mode));
+ return (MEM_P (inner) && general_operand (op, mode));
}
/* Return 1 if OP is a valid indirect memory reference with mode MODE;
@@ -1347,7 +1345,7 @@ indirect_operand (rtx op, enum machine_mode mode)
{
/* Before reload, a SUBREG isn't in memory (see memory_operand, above). */
if (! reload_completed
- && GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM)
+ && GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))
{
int offset = SUBREG_BYTE (op);
rtx inner = SUBREG_REG (op);
@@ -1367,7 +1365,7 @@ indirect_operand (rtx op, enum machine_mode mode)
&& general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
}
- return (GET_CODE (op) == MEM
+ return (MEM_P (op)
&& memory_operand (op, mode)
&& general_operand (XEXP (op, 0), Pmode));
}
@@ -1379,7 +1377,7 @@ int
comparison_operator (rtx op, enum machine_mode mode)
{
return ((mode == VOIDmode || GET_MODE (op) == mode)
- && GET_RTX_CLASS (GET_CODE (op)) == '<');
+ && COMPARISON_P (op));
}
/* If BODY is an insn body that uses ASM_OPERANDS,
@@ -1600,7 +1598,7 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
return template;
}
-/* Check if an asm_operand matches it's constraints.
+/* Check if an asm_operand matches its constraints.
Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
int
@@ -1609,8 +1607,7 @@ asm_operand_ok (rtx op, const char *constraint)
int result = 0;
/* Use constrain_operands after reload. */
- if (reload_completed)
- abort ();
+ gcc_assert (!reload_completed);
while (*constraint)
{
@@ -1668,7 +1665,7 @@ asm_operand_ok (rtx op, const char *constraint)
Match any memory and hope things are resolved after reload. */
- if (GET_CODE (op) == MEM
+ if (MEM_P (op)
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
@@ -1676,7 +1673,7 @@ asm_operand_ok (rtx op, const char *constraint)
break;
case '>':
- if (GET_CODE (op) == MEM
+ if (MEM_P (op)
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
@@ -1710,11 +1707,7 @@ asm_operand_ok (rtx op, const char *constraint)
/* Fall through. */
case 'i':
- if (CONSTANT_P (op)
-#ifdef LEGITIMATE_PIC_OPERAND_P
- && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
-#endif
- )
+ if (CONSTANT_P (op) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)))
result = 1;
break;
@@ -1871,7 +1864,7 @@ find_constant_term_loc (rtx *p)
int
offsettable_memref_p (rtx op)
{
- return ((GET_CODE (op) == MEM)
+ return ((MEM_P (op))
&& offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
}
@@ -1881,7 +1874,7 @@ offsettable_memref_p (rtx op)
int
offsettable_nonstrict_memref_p (rtx op)
{
- return ((GET_CODE (op) == MEM)
+ return ((MEM_P (op))
&& offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
}
@@ -1940,7 +1933,7 @@ offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
return good;
}
- if (GET_RTX_CLASS (ycode) == 'a')
+ if (GET_RTX_CLASS (ycode) == RTX_AUTOINC)
return 0;
/* The offset added here is chosen as the maximum offset that
@@ -1989,6 +1982,7 @@ extract_insn_cached (rtx insn)
extract_insn (insn);
recog_data.insn = insn;
}
+
/* Do cached extract_insn, constrain_operands and complain about failures.
Used by insn_attrtab. */
void
@@ -1999,6 +1993,7 @@ extract_constrain_insn_cached (rtx insn)
&& !constrain_operands (reload_completed))
fatal_insn_not_found (insn);
}
+
/* Do cached constrain_operands and complain about failures. */
int
constrain_operands_cached (int strict)
@@ -2054,8 +2049,7 @@ extract_insn (rtx insn)
/* This insn is an `asm' with operands. */
/* expand_asm_operands makes sure there aren't too many operands. */
- if (noperands > MAX_RECOG_OPERANDS)
- abort ();
+ gcc_assert (noperands <= MAX_RECOG_OPERANDS);
/* Now get the operand values and constraints out of the insn. */
decode_asm_operands (body, recog_data.operand,
@@ -2103,8 +2097,7 @@ extract_insn (rtx insn)
: recog_data.constraints[i][0] == '+' ? OP_INOUT
: OP_IN);
- if (recog_data.n_alternatives > MAX_RECOG_ALTERNATIVES)
- abort ();
+ gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
}
/* After calling extract_insn, you can use this function to extract some
@@ -2129,7 +2122,7 @@ preprocess_constraints (void)
for (j = 0; j < recog_data.n_alternatives; j++)
{
- op_alt[j].class = NO_REGS;
+ op_alt[j].cl = NO_REGS;
op_alt[j].constraint = p;
op_alt[j].matches = -1;
op_alt[j].matched = -1;
@@ -2204,12 +2197,14 @@ preprocess_constraints (void)
case 'p':
op_alt[j].is_address = 1;
- op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
- [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
+ [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
break;
- case 'g': case 'r':
- op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) GENERAL_REGS];
+ case 'g':
+ case 'r':
+ op_alt[j].cl =
+ reg_class_subunion[(int) op_alt[j].cl][(int) GENERAL_REGS];
break;
default:
@@ -2221,16 +2216,17 @@ preprocess_constraints (void)
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
op_alt[j].is_address = 1;
- op_alt[j].class
+ op_alt[j].cl
= (reg_class_subunion
- [(int) op_alt[j].class]
- [(int) MODE_BASE_REG_CLASS (VOIDmode)]);
+ [(int) op_alt[j].cl]
+ [(int) base_reg_class (VOIDmode, ADDRESS,
+ SCRATCH)]);
break;
}
- op_alt[j].class
+ op_alt[j].cl
= (reg_class_subunion
- [(int) op_alt[j].class]
+ [(int) op_alt[j].cl]
[(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
break;
}
@@ -2295,6 +2291,7 @@ constrain_operands (int strict)
do
{
+ int seen_earlyclobber_at = -1;
int opno;
int lose = 0;
funny_match_index = 0;
@@ -2313,12 +2310,12 @@ constrain_operands (int strict)
/* A unary operator may be accepted by the predicate, but it
is irrelevant for matching constraints. */
- if (GET_RTX_CLASS (GET_CODE (op)) == '1')
+ if (UNARY_P (op))
op = XEXP (op, 0);
if (GET_CODE (op) == SUBREG)
{
- if (GET_CODE (SUBREG_REG (op)) == REG
+ if (REG_P (SUBREG_REG (op))
&& REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
GET_MODE (SUBREG_REG (op)),
@@ -2357,6 +2354,8 @@ constrain_operands (int strict)
case '&':
earlyclobber[opno] = 1;
+ if (seen_earlyclobber_at < 0)
+ seen_earlyclobber_at = opno;
break;
case '0': case '1': case '2': case '3': case '4':
@@ -2386,9 +2385,9 @@ constrain_operands (int strict)
/* A unary operator may be accepted by the predicate,
but it is irrelevant for matching constraints. */
- if (GET_RTX_CLASS (GET_CODE (op1)) == '1')
+ if (UNARY_P (op1))
op1 = XEXP (op1, 0);
- if (GET_RTX_CLASS (GET_CODE (op2)) == '1')
+ if (UNARY_P (op2))
op2 = XEXP (op2, 0);
val = operands_match_p (op1, op2);
@@ -2424,16 +2423,22 @@ constrain_operands (int strict)
break;
/* No need to check general_operand again;
- it was done in insn-recog.c. */
+ it was done in insn-recog.c. Well, except that reload
+ doesn't check the validity of its replacements, but
+ that should only matter when there's a bug. */
case 'g':
/* Anything goes unless it is a REG and really has a hard reg
but the hard reg is not in the class GENERAL_REGS. */
- if (strict < 0
- || GENERAL_REGS == ALL_REGS
- || GET_CODE (op) != REG
- || (reload_in_progress
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)
- || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
+ if (REG_P (op))
+ {
+ if (strict < 0
+ || GENERAL_REGS == ALL_REGS
+ || (reload_in_progress
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER)
+ || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
+ win = 1;
+ }
+ else if (strict < 0 || general_operand (op, mode))
win = 1;
break;
@@ -2447,7 +2452,7 @@ constrain_operands (int strict)
case 'm':
/* Memory operands must be valid, to the extent
required by STRICT. */
- if (GET_CODE (op) == MEM)
+ if (MEM_P (op))
{
if (strict > 0
&& !strict_memory_address_p (GET_MODE (op),
@@ -2462,20 +2467,20 @@ constrain_operands (int strict)
else if (strict < 0 && CONSTANT_P (op))
win = 1;
/* During reload, accept a pseudo */
- else if (reload_in_progress && GET_CODE (op) == REG
+ else if (reload_in_progress && REG_P (op)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)
win = 1;
break;
case '<':
- if (GET_CODE (op) == MEM
+ if (MEM_P (op)
&& (GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
win = 1;
break;
case '>':
- if (GET_CODE (op) == MEM
+ if (MEM_P (op)
&& (GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
win = 1;
@@ -2527,12 +2532,12 @@ constrain_operands (int strict)
break;
case 'V':
- if (GET_CODE (op) == MEM
+ if (MEM_P (op)
&& ((strict > 0 && ! offsettable_memref_p (op))
|| (strict < 0
- && !(CONSTANT_P (op) || GET_CODE (op) == MEM))
+ && !(CONSTANT_P (op) || MEM_P (op)))
|| (reload_in_progress
- && !(GET_CODE (op) == REG
+ && !(REG_P (op)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER))))
win = 1;
break;
@@ -2542,28 +2547,28 @@ constrain_operands (int strict)
|| (strict == 0 && offsettable_nonstrict_memref_p (op))
/* Before reload, accept what reload can handle. */
|| (strict < 0
- && (CONSTANT_P (op) || GET_CODE (op) == MEM))
+ && (CONSTANT_P (op) || MEM_P (op)))
/* During reload, accept a pseudo */
- || (reload_in_progress && GET_CODE (op) == REG
+ || (reload_in_progress && REG_P (op)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER))
win = 1;
break;
default:
{
- enum reg_class class;
+ enum reg_class cl;
- class = (c == 'r'
+ cl = (c == 'r'
? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
- if (class != NO_REGS)
+ if (cl != NO_REGS)
{
if (strict < 0
|| (strict == 0
- && GET_CODE (op) == REG
+ && REG_P (op)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)
|| (strict == 0 && GET_CODE (op) == SCRATCH)
- || (GET_CODE (op) == REG
- && reg_fits_class_p (op, class, offset, mode)))
+ || (REG_P (op)
+ && reg_fits_class_p (op, cl, offset, mode)))
win = 1;
}
#ifdef EXTRA_CONSTRAINT_STR
@@ -2572,12 +2577,12 @@ constrain_operands (int strict)
else if (EXTRA_MEMORY_CONSTRAINT (c, p)
/* Every memory operand can be reloaded to fit. */
- && ((strict < 0 && GET_CODE (op) == MEM)
+ && ((strict < 0 && MEM_P (op))
/* Before reload, accept what reload can turn
into mem. */
|| (strict < 0 && CONSTANT_P (op))
/* During reload, accept a pseudo */
- || (reload_in_progress && GET_CODE (op) == REG
+ || (reload_in_progress && REG_P (op)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)))
win = 1;
else if (EXTRA_ADDRESS_CONSTRAINT (c, p)
@@ -2605,15 +2610,17 @@ constrain_operands (int strict)
/* See if any earlyclobber operand conflicts with some other
operand. */
- if (strict > 0)
- for (eopno = 0; eopno < recog_data.n_operands; eopno++)
+ if (strict > 0 && seen_earlyclobber_at >= 0)
+ for (eopno = seen_earlyclobber_at;
+ eopno < recog_data.n_operands;
+ eopno++)
/* Ignore earlyclobber operands now in memory,
because we would often report failure when we have
two memory operands, one of which was formerly a REG. */
if (earlyclobber[eopno]
- && GET_CODE (recog_data.operand[eopno]) == REG)
+ && REG_P (recog_data.operand[eopno]))
for (opno = 0; opno < recog_data.n_operands; opno++)
- if ((GET_CODE (recog_data.operand[opno]) == MEM
+ if ((MEM_P (recog_data.operand[opno])
|| recog_data.operand_type[opno] != OP_OUT)
&& opno != eopno
/* Ignore things like match_operator operands. */
@@ -2656,19 +2663,23 @@ constrain_operands (int strict)
If REG occupies multiple hard regs, all of them must be in CLASS. */
int
-reg_fits_class_p (rtx operand, enum reg_class class, int offset,
+reg_fits_class_p (rtx operand, enum reg_class cl, int offset,
enum machine_mode mode)
{
int regno = REGNO (operand);
+
+ if (cl == NO_REGS)
+ return 0;
+
if (regno < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ && TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
regno + offset))
{
int sr;
regno += offset;
- for (sr = HARD_REGNO_NREGS (regno, mode) - 1;
+ for (sr = hard_regno_nregs[regno][mode] - 1;
sr > 0; sr--)
- if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ if (! TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
regno + sr))
break;
return sr == 0;
@@ -2692,9 +2703,7 @@ split_insn (rtx insn)
return NULL_RTX;
/* try_split returns the NOTE that INSN became. */
- PUT_CODE (insn, NOTE);
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ SET_INSN_DELETED (insn);
/* ??? Coddle to md files that generate subregs in post-reload
splitters instead of computing the proper hard register. */
@@ -2773,7 +2782,7 @@ split_all_insns (int upd_life)
BB boundary we are interested in will be set to
previous one. */
- while (GET_CODE (last) == BARRIER)
+ while (BARRIER_P (last))
last = PREV_INSN (last);
SET_BIT (blocks, bb->index);
changed = true;
@@ -2795,7 +2804,7 @@ split_all_insns (int upd_life)
if (changed && upd_life)
update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_DEATH_NOTES | PROP_REG_INFO);
+ PROP_DEATH_NOTES);
#ifdef ENABLE_CHECKING
verify_flow_info ();
@@ -2807,7 +2816,7 @@ split_all_insns (int upd_life)
/* Same as split_all_insns, but do not expect CFG to be available.
Used by machine dependent reorg passes. */
-void
+unsigned int
split_all_insns_noflow (void)
{
rtx next, insn;
@@ -2837,6 +2846,7 @@ split_all_insns_noflow (void)
split_insn (insn);
}
}
+ return 0;
}
#ifdef HAVE_peephole2
@@ -2848,6 +2858,8 @@ struct peep2_insn_data
static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
static int peep2_current;
+/* The number of instructions available to match a peep2. */
+int peep2_current_count;
/* A non-insn marker indicating the last insn of the block.
The live_before regset for this element is correct, indicating
@@ -2861,15 +2873,12 @@ static int peep2_current;
rtx
peep2_next_insn (int n)
{
- if (n >= MAX_INSNS_PER_PEEP2 + 1)
- abort ();
+ gcc_assert (n <= peep2_current_count);
n += peep2_current;
if (n >= MAX_INSNS_PER_PEEP2 + 1)
n -= MAX_INSNS_PER_PEEP2 + 1;
- if (peep2_insn_data[n].insn == PEEP2_EOB)
- return NULL_RTX;
return peep2_insn_data[n].insn;
}
@@ -2879,15 +2888,13 @@ peep2_next_insn (int n)
int
peep2_regno_dead_p (int ofs, int regno)
{
- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
- abort ();
+ gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
ofs += peep2_current;
if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
ofs -= MAX_INSNS_PER_PEEP2 + 1;
- if (peep2_insn_data[ofs].insn == NULL_RTX)
- abort ();
+ gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
}
@@ -2899,18 +2906,16 @@ peep2_reg_dead_p (int ofs, rtx reg)
{
int regno, n;
- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
- abort ();
+ gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
ofs += peep2_current;
if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
ofs -= MAX_INSNS_PER_PEEP2 + 1;
- if (peep2_insn_data[ofs].insn == NULL_RTX)
- abort ();
+ gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
regno = REGNO (reg);
- n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ n = hard_regno_nregs[regno][GET_MODE (reg)];
while (--n >= 0)
if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
return 0;
@@ -2933,12 +2938,12 @@ peep2_find_free_register (int from, int to, const char *class_str,
enum machine_mode mode, HARD_REG_SET *reg_set)
{
static int search_ofs;
- enum reg_class class;
+ enum reg_class cl;
HARD_REG_SET live;
int i;
- if (from >= MAX_INSNS_PER_PEEP2 + 1 || to >= MAX_INSNS_PER_PEEP2 + 1)
- abort ();
+ gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
+ gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
from += peep2_current;
if (from >= MAX_INSNS_PER_PEEP2 + 1)
@@ -2947,8 +2952,7 @@ peep2_find_free_register (int from, int to, const char *class_str,
if (to >= MAX_INSNS_PER_PEEP2 + 1)
to -= MAX_INSNS_PER_PEEP2 + 1;
- if (peep2_insn_data[from].insn == NULL_RTX)
- abort ();
+ gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
while (from != to)
@@ -2957,13 +2961,12 @@ peep2_find_free_register (int from, int to, const char *class_str,
if (++from >= MAX_INSNS_PER_PEEP2 + 1)
from = 0;
- if (peep2_insn_data[from].insn == NULL_RTX)
- abort ();
+ gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
IOR_HARD_REG_SET (live, this_live);
}
- class = (class_str[0] == 'r' ? GENERAL_REGS
+ cl = (class_str[0] == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -2984,7 +2987,7 @@ peep2_find_free_register (int from, int to, const char *class_str,
if (fixed_regs[regno])
continue;
/* Make sure the register is of the right class. */
- if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno))
+ if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno))
continue;
/* And can support the mode we need. */
if (! HARD_REGNO_MODE_OK (regno, mode))
@@ -2998,7 +3001,7 @@ peep2_find_free_register (int from, int to, const char *class_str,
continue;
success = 1;
- for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+ for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
{
if (TEST_HARD_REG_BIT (*reg_set, regno + j)
|| TEST_HARD_REG_BIT (live, regno + j))
@@ -3009,7 +3012,7 @@ peep2_find_free_register (int from, int to, const char *class_str,
}
if (success)
{
- for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+ for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
SET_HARD_REG_BIT (*reg_set, regno + j);
/* Start the next search with the next register. */
@@ -3027,10 +3030,9 @@ peep2_find_free_register (int from, int to, const char *class_str,
/* Perform the peephole2 optimization pass. */
-void
-peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
+static void
+peephole2_optimize (void)
{
- regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2];
rtx insn, prev;
regset live;
int i;
@@ -3040,12 +3042,13 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
bool changed;
#endif
bool do_cleanup_cfg = false;
+ bool do_global_life_update = false;
bool do_rebuild_jump_labels = false;
/* Initialize the regsets we're going to use. */
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
- peep2_insn_data[i].live_before = INITIALIZE_REG_SET (rs_heads[i]);
- live = INITIALIZE_REG_SET (rs_heads[i]);
+ peep2_insn_data[i].live_before = ALLOC_REG_SET (&reg_obstack);
+ live = ALLOC_REG_SET (&reg_obstack);
#ifdef HAVE_conditional_execution
blocks = sbitmap_alloc (last_basic_block);
@@ -3058,17 +3061,20 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
FOR_EACH_BB_REVERSE (bb)
{
struct propagate_block_info *pbi;
+ reg_set_iterator rsi;
+ unsigned int j;
/* Indicate that all slots except the last holds invalid data. */
for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
peep2_insn_data[i].insn = NULL_RTX;
+ peep2_current_count = 0;
/* Indicate that the last slot contains live_after data. */
peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
peep2_current = MAX_INSNS_PER_PEEP2;
/* Start up propagation. */
- COPY_REG_SET (live, bb->global_live_at_end);
+ COPY_REG_SET (live, bb->il.rtl->global_live_at_end);
COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
#ifdef HAVE_conditional_execution
@@ -3090,12 +3096,25 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
/* Record this insn. */
if (--peep2_current < 0)
peep2_current = MAX_INSNS_PER_PEEP2;
+ if (peep2_current_count < MAX_INSNS_PER_PEEP2
+ && peep2_insn_data[peep2_current].insn == NULL_RTX)
+ peep2_current_count++;
peep2_insn_data[peep2_current].insn = insn;
propagate_one_insn (pbi, insn);
COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
- /* Match the peephole. */
- try = peephole2_insns (PATTERN (insn), insn, &match_len);
+ if (RTX_FRAME_RELATED_P (insn))
+ {
+ /* If an insn has RTX_FRAME_RELATED_P set, peephole
+ substitution would lose the
+ REG_FRAME_RELATED_EXPR that is attached. */
+ peep2_current_count = 0;
+ try = NULL;
+ }
+ else
+ /* Match the peephole. */
+ try = peephole2_insns (PATTERN (insn), insn, &match_len);
+
if (try != NULL)
{
/* If we are splitting a CALL_INSN, look for the CALL_INSN
@@ -3110,20 +3129,19 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
if (j >= MAX_INSNS_PER_PEEP2 + 1)
j -= MAX_INSNS_PER_PEEP2 + 1;
old_insn = peep2_insn_data[j].insn;
- if (GET_CODE (old_insn) != CALL_INSN)
+ if (!CALL_P (old_insn))
continue;
was_call = true;
new_insn = try;
while (new_insn != NULL_RTX)
{
- if (GET_CODE (new_insn) == CALL_INSN)
+ if (CALL_P (new_insn))
break;
new_insn = NEXT_INSN (new_insn);
}
- if (new_insn == NULL_RTX)
- abort ();
+ gcc_assert (new_insn != NULL_RTX);
CALL_INSN_FUNCTION_USAGE (new_insn)
= CALL_INSN_FUNCTION_USAGE (old_insn);
@@ -3135,7 +3153,6 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
{
case REG_NORETURN:
case REG_SETJMP:
- case REG_ALWAYS_RETURN:
REG_NOTES (new_insn)
= gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
XEXP (note, 0),
@@ -3152,8 +3169,7 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
if (j >= MAX_INSNS_PER_PEEP2 + 1)
j -= MAX_INSNS_PER_PEEP2 + 1;
old_insn = peep2_insn_data[j].insn;
- if (GET_CODE (old_insn) == CALL_INSN)
- abort ();
+ gcc_assert (!CALL_P (old_insn));
}
break;
}
@@ -3175,14 +3191,14 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
if (note || (was_call && nonlocal_goto_handler_labels))
{
edge eh_edge;
+ edge_iterator ei;
- for (eh_edge = bb->succ; eh_edge
- ; eh_edge = eh_edge->succ_next)
+ FOR_EACH_EDGE (eh_edge, ei, bb->succs)
if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
break;
for (x = try ; x != before_try ; x = PREV_INSN (x))
- if (GET_CODE (x) == CALL_INSN
+ if (CALL_P (x)
|| (flag_non_call_exceptions
&& may_trap_p (PATTERN (x))
&& !find_reg_note (x, REG_EH_REGION, NULL)))
@@ -3201,7 +3217,7 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
nfte = split_block (bb, x);
flags = (eh_edge->flags
& (EDGE_EH | EDGE_ABNORMAL));
- if (GET_CODE (x) == CALL_INSN)
+ if (CALL_P (x))
flags |= EDGE_ABNORMAL_CALL;
nehe = make_edge (nfte->src, eh_edge->dest,
flags);
@@ -3237,6 +3253,7 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
peep2_insn_data[i].insn = NULL_RTX;
peep2_insn_data[peep2_current].insn = PEEP2_EOB;
+ peep2_current_count = 0;
#else
/* Back up lifetime information past the end of the
newly created sequence. */
@@ -3252,6 +3269,9 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
{
if (--i < 0)
i = MAX_INSNS_PER_PEEP2;
+ if (peep2_current_count < MAX_INSNS_PER_PEEP2
+ && peep2_insn_data[i].insn == NULL_RTX)
+ peep2_current_count++;
peep2_insn_data[i].insn = x;
propagate_one_insn (pbi, x);
COPY_REG_SET (peep2_insn_data[i].live_before, live);
@@ -3269,7 +3289,7 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
/* If we generated a jump instruction, it won't have
JUMP_LABEL set. Recompute after we're done. */
for (x = try; x != before_try; x = PREV_INSN (x))
- if (GET_CODE (x) == JUMP_INSN)
+ if (JUMP_P (x))
{
do_rebuild_jump_labels = true;
break;
@@ -3281,6 +3301,15 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
break;
}
+ /* Some peepholes can decide the don't need one or more of their
+ inputs. If this happens, local life update is not enough. */
+ EXECUTE_IF_AND_COMPL_IN_BITMAP (bb->il.rtl->global_live_at_start, live,
+ 0, j, rsi)
+ {
+ do_global_life_update = true;
+ break;
+ }
+
free_propagate_block_info (pbi);
}
@@ -3297,8 +3326,10 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
if (do_cleanup_cfg)
{
cleanup_cfg (0);
- update_life_info (0, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
+ do_global_life_update = true;
}
+ if (do_global_life_update)
+ update_life_info (0, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
#ifdef HAVE_conditional_execution
else
{
@@ -3323,10 +3354,9 @@ store_data_bypass_p (rtx out_insn, rtx in_insn)
rtx out_set, in_set;
in_set = single_set (in_insn);
- if (! in_set)
- abort ();
+ gcc_assert (in_set);
- if (GET_CODE (SET_DEST (in_set)) != MEM)
+ if (!MEM_P (SET_DEST (in_set)))
return false;
out_set = single_set (out_insn);
@@ -3341,8 +3371,7 @@ store_data_bypass_p (rtx out_insn, rtx in_insn)
int i;
out_pat = PATTERN (out_insn);
- if (GET_CODE (out_pat) != PARALLEL)
- abort ();
+ gcc_assert (GET_CODE (out_pat) == PARALLEL);
for (i = 0; i < XVECLEN (out_pat, 0); i++)
{
@@ -3351,8 +3380,7 @@ store_data_bypass_p (rtx out_insn, rtx in_insn)
if (GET_CODE (exp) == CLOBBER)
continue;
- if (GET_CODE (exp) != SET)
- abort ();
+ gcc_assert (GET_CODE (exp) == SET);
if (reg_mentioned_p (SET_DEST (exp), SET_DEST (in_set)))
return false;
@@ -3375,9 +3403,8 @@ if_test_bypass_p (rtx out_insn, rtx in_insn)
in_set = single_set (in_insn);
if (! in_set)
{
- if (GET_CODE (in_insn) == JUMP_INSN || GET_CODE (in_insn) == CALL_INSN)
- return false;
- abort ();
+ gcc_assert (JUMP_P (in_insn) || CALL_P (in_insn));
+ return false;
}
if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE)
@@ -3397,8 +3424,7 @@ if_test_bypass_p (rtx out_insn, rtx in_insn)
int i;
out_pat = PATTERN (out_insn);
- if (GET_CODE (out_pat) != PARALLEL)
- abort ();
+ gcc_assert (GET_CODE (out_pat) == PARALLEL);
for (i = 0; i < XVECLEN (out_pat, 0); i++)
{
@@ -3407,8 +3433,7 @@ if_test_bypass_p (rtx out_insn, rtx in_insn)
if (GET_CODE (exp) == CLOBBER)
continue;
- if (GET_CODE (exp) != SET)
- abort ();
+ gcc_assert (GET_CODE (exp) == SET);
if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
|| reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
@@ -3418,3 +3443,124 @@ if_test_bypass_p (rtx out_insn, rtx in_insn)
return true;
}
+
+static bool
+gate_handle_peephole2 (void)
+{
+ return (optimize > 0 && flag_peephole2);
+}
+
+static unsigned int
+rest_of_handle_peephole2 (void)
+{
+#ifdef HAVE_peephole2
+ peephole2_optimize ();
+#endif
+ return 0;
+}
+
+struct tree_opt_pass pass_peephole2 =
+{
+ "peephole2", /* name */
+ gate_handle_peephole2, /* gate */
+ rest_of_handle_peephole2, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_PEEPHOLE2, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 'z' /* letter */
+};
+
+static unsigned int
+rest_of_handle_split_all_insns (void)
+{
+ split_all_insns (1);
+ return 0;
+}
+
+struct tree_opt_pass pass_split_all_insns =
+{
+ "split1", /* name */
+ NULL, /* gate */
+ rest_of_handle_split_all_insns, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
+
+/* The placement of the splitting that we do for shorten_branches
+ depends on whether regstack is used by the target or not. */
+static bool
+gate_do_final_split (void)
+{
+#if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+struct tree_opt_pass pass_split_for_shorten_branches =
+{
+ "split3", /* name */
+ gate_do_final_split, /* gate */
+ split_all_insns_noflow, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_SHORTEN_BRANCH, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
+
+
+static bool
+gate_handle_split_before_regstack (void)
+{
+#if defined (HAVE_ATTR_length) && defined (STACK_REGS)
+ /* If flow2 creates new instructions which need splitting
+ and scheduling after reload is not done, they might not be
+ split until final which doesn't allow splitting
+ if HAVE_ATTR_length. */
+# ifdef INSN_SCHEDULING
+ return (optimize && !flag_schedule_insns_after_reload);
+# else
+ return (optimize);
+# endif
+#else
+ return 0;
+#endif
+}
+
+struct tree_opt_pass pass_split_before_regstack =
+{
+ "split2", /* name */
+ gate_handle_split_before_regstack, /* gate */
+ rest_of_handle_split_all_insns, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_SHORTEN_BRANCH, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
diff --git a/contrib/gcc/reload.c b/contrib/gcc/reload.c
index 9eae9ff..08a393f 100644
--- a/contrib/gcc/reload.c
+++ b/contrib/gcc/reload.c
@@ -1,6 +1,7 @@
/* Search an insn for pseudo regs that must be in hard regs and are not.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+ Inc.
This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* This file contains subroutines used only from the file reload1.c.
It knows how to scan one insn for operands and values
@@ -27,6 +28,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
ought to be used instead.
Before processing the first insn of the function, call `init_reload'.
+ init_reload actually has to be called earlier anyway.
To scan an insn, call `find_reloads'. This does two things:
1. sets up tables describing which values must be reloaded
@@ -98,6 +100,7 @@ a register with any other reload. */
#include "recog.h"
#include "reload.h"
#include "regs.h"
+#include "addresses.h"
#include "hard-reg-set.h"
#include "flags.h"
#include "real.h"
@@ -105,14 +108,20 @@ a register with any other reload. */
#include "function.h"
#include "toplev.h"
#include "params.h"
+#include "target.h"
-#ifndef REGNO_MODE_OK_FOR_BASE_P
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
-#endif
+/* True if X is a constant that can be forced into the constant pool. */
+#define CONST_POOL_OK_P(X) \
+ (CONSTANT_P (X) \
+ && GET_CODE (X) != HIGH \
+ && !targetm.cannot_force_const_mem (X))
+
+/* True if C is a non-empty register class that has too few registers
+ to be safely used as a reload target class. */
+#define SMALL_REGISTER_CLASS_P(C) \
+ (reg_class_size [(C)] == 1 \
+ || (reg_class_size [(C)] >= 1 && CLASS_LIKELY_SPILLED_P (C)))
-#ifndef REG_MODE_OK_FOR_BASE_P
-#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
-#endif
/* All reloads of the current insn are recorded here. See reload.h for
comments. */
@@ -203,8 +212,8 @@ static int output_reloadnum;
/* Compare two RTX's. */
#define MATCHES(x, y) \
- (x == y || (x != 0 && (GET_CODE (x) == REG \
- ? GET_CODE (y) == REG && REGNO (x) == REGNO (y) \
+ (x == y || (x != 0 && (REG_P (x) \
+ ? REG_P (y) && REGNO (x) == REGNO (y) \
: rtx_equal_p (x, y) && ! side_effects_p (x))))
/* Indicates if two reloads purposes are for similar enough things that we
@@ -235,12 +244,11 @@ static int output_reloadnum;
? RELOAD_FOR_OUTADDR_ADDRESS \
: (type)))
-#ifdef HAVE_SECONDARY_RELOADS
static int push_secondary_reload (int, rtx, int, int, enum reg_class,
enum machine_mode, enum reload_type,
- enum insn_code *);
-#endif
-static enum reg_class find_valid_class (enum machine_mode, int, unsigned int);
+ enum insn_code *, secondary_reload_info *);
+static enum reg_class find_valid_class (enum machine_mode, enum machine_mode,
+ int, unsigned int);
static int reload_inner_reg_of_subreg (rtx, enum machine_mode, int);
static void push_replacement (rtx *, int, enum machine_mode);
static void dup_replacements (rtx *, rtx *);
@@ -262,7 +270,8 @@ static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *,
static rtx subst_reg_equivs (rtx, rtx);
static rtx subst_indexed_address (rtx);
static void update_auto_inc_notes (rtx, int, int);
-static int find_reloads_address_1 (enum machine_mode, rtx, int, rtx *,
+static int find_reloads_address_1 (enum machine_mode, rtx, int,
+ enum rtx_code, enum rtx_code, rtx *,
int, enum reload_type,int, rtx);
static void find_reloads_address_part (rtx, rtx *, enum reg_class,
enum machine_mode, int,
@@ -271,9 +280,27 @@ static rtx find_reloads_subreg_address (rtx, int, int, enum reload_type,
int, rtx);
static void copy_replacements_1 (rtx *, rtx *, int);
static int find_inc_amount (rtx, rtx);
-
-#ifdef HAVE_SECONDARY_RELOADS
+static int refers_to_mem_for_reload_p (rtx);
+static int refers_to_regno_for_reload_p (unsigned int, unsigned int,
+ rtx, rtx *);
+
+/* Add NEW to reg_equiv_alt_mem_list[REGNO] if it's not present in the
+ list yet. */
+
+static void
+push_reg_equiv_alt_mem (int regno, rtx mem)
+{
+ rtx it;
+
+ for (it = reg_equiv_alt_mem_list [regno]; it; it = XEXP (it, 1))
+ if (rtx_equal_p (XEXP (it, 0), mem))
+ return;
+ reg_equiv_alt_mem_list [regno]
+ = alloc_EXPR_LIST (REG_EQUIV, mem,
+ reg_equiv_alt_mem_list [regno]);
+}
+
/* Determine if any secondary reloads are needed for loading (if IN_P is
nonzero) or storing (if IN_P is zero) X to or from a reload register of
register class RELOAD_CLASS in mode RELOAD_MODE. If secondary reloads
@@ -287,16 +314,18 @@ static int
push_secondary_reload (int in_p, rtx x, int opnum, int optional,
enum reg_class reload_class,
enum machine_mode reload_mode, enum reload_type type,
- enum insn_code *picode)
+ enum insn_code *picode, secondary_reload_info *prev_sri)
{
enum reg_class class = NO_REGS;
+ enum reg_class scratch_class;
enum machine_mode mode = reload_mode;
enum insn_code icode = CODE_FOR_nothing;
- enum reg_class t_class = NO_REGS;
- enum machine_mode t_mode = VOIDmode;
enum insn_code t_icode = CODE_FOR_nothing;
enum reload_type secondary_type;
int s_reload, t_reload = -1;
+ const char *scratch_constraint;
+ char letter;
+ secondary_reload_info sri;
if (type == RELOAD_FOR_INPUT_ADDRESS
|| type == RELOAD_FOR_OUTPUT_ADDRESS
@@ -324,40 +353,25 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
a secondary reload is needed since whether or not a reload is needed
might be sensitive to the form of the MEM. */
- if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
+ if (REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER
&& reg_equiv_mem[REGNO (x)] != 0)
x = reg_equiv_mem[REGNO (x)];
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- if (in_p)
- class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x);
-#endif
-
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- if (! in_p)
- class = SECONDARY_OUTPUT_RELOAD_CLASS (reload_class, reload_mode, x);
-#endif
+ sri.icode = CODE_FOR_nothing;
+ sri.prev_sri = prev_sri;
+ class = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
+ icode = sri.icode;
/* If we don't need any secondary registers, done. */
- if (class == NO_REGS)
+ if (class == NO_REGS && icode == CODE_FOR_nothing)
return -1;
- /* Get a possible insn to use. If the predicate doesn't accept X, don't
- use the insn. */
-
- icode = (in_p ? reload_in_optab[(int) reload_mode]
- : reload_out_optab[(int) reload_mode]);
-
- if (icode != CODE_FOR_nothing
- && insn_data[(int) icode].operand[in_p].predicate
- && (! (insn_data[(int) icode].operand[in_p].predicate) (x, reload_mode)))
- icode = CODE_FOR_nothing;
+ if (class != NO_REGS)
+ t_reload = push_secondary_reload (in_p, x, opnum, optional, class,
+ reload_mode, type, &t_icode, &sri);
- /* If we will be using an insn, see if it can directly handle the reload
- register we will be using. If it can, the secondary reload is for a
- scratch register. If it can't, we will use the secondary reload for
- an intermediate register and require a tertiary reload for the scratch
- register. */
+ /* If we will be using an insn, the secondary reload is for a
+ scratch register. */
if (icode != CODE_FOR_nothing)
{
@@ -366,47 +380,29 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
in operand 1. Outputs should have an initial "=", which we must
skip. */
- enum reg_class insn_class;
-
- if (insn_data[(int) icode].operand[!in_p].constraint[0] == 0)
- insn_class = ALL_REGS;
- else
- {
- const char *insn_constraint
- = &insn_data[(int) icode].operand[!in_p].constraint[in_p];
- char insn_letter = *insn_constraint;
- insn_class
- = (insn_letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
- insn_constraint));
-
- if (insn_class == NO_REGS)
- abort ();
- if (in_p
- && insn_data[(int) icode].operand[!in_p].constraint[0] != '=')
- abort ();
- }
-
- /* The scratch register's constraint must start with "=&". */
- if (insn_data[(int) icode].operand[2].constraint[0] != '='
- || insn_data[(int) icode].operand[2].constraint[1] != '&')
- abort ();
-
- if (reg_class_subset_p (reload_class, insn_class))
- mode = insn_data[(int) icode].operand[2].mode;
- else
- {
- const char *t_constraint
- = &insn_data[(int) icode].operand[2].constraint[2];
- char t_letter = *t_constraint;
- class = insn_class;
- t_mode = insn_data[(int) icode].operand[2].mode;
- t_class = (t_letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT ((unsigned char) t_letter,
- t_constraint));
- t_icode = icode;
- icode = CODE_FOR_nothing;
- }
+ /* ??? It would be useful to be able to handle only two, or more than
+ three, operands, but for now we can only handle the case of having
+ exactly three: output, input and one temp/scratch. */
+ gcc_assert (insn_data[(int) icode].n_operands == 3);
+
+ /* ??? We currently have no way to represent a reload that needs
+ an icode to reload from an intermediate tertiary reload register.
+ We should probably have a new field in struct reload to tag a
+ chain of scratch operand reloads onto. */
+ gcc_assert (class == NO_REGS);
+
+ scratch_constraint = insn_data[(int) icode].operand[2].constraint;
+ gcc_assert (*scratch_constraint == '=');
+ scratch_constraint++;
+ if (*scratch_constraint == '&')
+ scratch_constraint++;
+ letter = *scratch_constraint;
+ scratch_class = (letter == 'r' ? GENERAL_REGS
+ : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
+ scratch_constraint));
+
+ class = scratch_class;
+ mode = insn_data[(int) icode].operand[2].mode;
}
/* This case isn't valid, so fail. Reload is allowed to use the same
@@ -423,71 +419,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
Allow this when a reload_in/out pattern is being used. I.e. assume
that the generated code handles this case. */
- if (in_p && class == reload_class && icode == CODE_FOR_nothing
- && t_icode == CODE_FOR_nothing)
- abort ();
-
- /* If we need a tertiary reload, see if we have one we can reuse or else
- make a new one. */
-
- if (t_class != NO_REGS)
- {
- for (t_reload = 0; t_reload < n_reloads; t_reload++)
- if (rld[t_reload].secondary_p
- && (reg_class_subset_p (t_class, rld[t_reload].class)
- || reg_class_subset_p (rld[t_reload].class, t_class))
- && ((in_p && rld[t_reload].inmode == t_mode)
- || (! in_p && rld[t_reload].outmode == t_mode))
- && ((in_p && (rld[t_reload].secondary_in_icode
- == CODE_FOR_nothing))
- || (! in_p &&(rld[t_reload].secondary_out_icode
- == CODE_FOR_nothing)))
- && (reg_class_size[(int) t_class] == 1 || SMALL_REGISTER_CLASSES)
- && MERGABLE_RELOADS (secondary_type,
- rld[t_reload].when_needed,
- opnum, rld[t_reload].opnum))
- {
- if (in_p)
- rld[t_reload].inmode = t_mode;
- if (! in_p)
- rld[t_reload].outmode = t_mode;
-
- if (reg_class_subset_p (t_class, rld[t_reload].class))
- rld[t_reload].class = t_class;
-
- rld[t_reload].opnum = MIN (rld[t_reload].opnum, opnum);
- rld[t_reload].optional &= optional;
- rld[t_reload].secondary_p = 1;
- if (MERGE_TO_OTHER (secondary_type, rld[t_reload].when_needed,
- opnum, rld[t_reload].opnum))
- rld[t_reload].when_needed = RELOAD_OTHER;
- }
-
- if (t_reload == n_reloads)
- {
- /* We need to make a new tertiary reload for this register class. */
- rld[t_reload].in = rld[t_reload].out = 0;
- rld[t_reload].class = t_class;
- rld[t_reload].inmode = in_p ? t_mode : VOIDmode;
- rld[t_reload].outmode = ! in_p ? t_mode : VOIDmode;
- rld[t_reload].reg_rtx = 0;
- rld[t_reload].optional = optional;
- rld[t_reload].inc = 0;
- /* Maybe we could combine these, but it seems too tricky. */
- rld[t_reload].nocombine = 1;
- rld[t_reload].in_reg = 0;
- rld[t_reload].out_reg = 0;
- rld[t_reload].opnum = opnum;
- rld[t_reload].when_needed = secondary_type;
- rld[t_reload].secondary_in_reload = -1;
- rld[t_reload].secondary_out_reload = -1;
- rld[t_reload].secondary_in_icode = CODE_FOR_nothing;
- rld[t_reload].secondary_out_icode = CODE_FOR_nothing;
- rld[t_reload].secondary_p = 1;
-
- n_reloads++;
- }
- }
+ gcc_assert (!in_p || class != reload_class || icode != CODE_FOR_nothing
+ || t_icode != CODE_FOR_nothing);
/* See if we can reuse an existing secondary reload. */
for (s_reload = 0; s_reload < n_reloads; s_reload++)
@@ -500,7 +433,7 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
|| (! in_p && rld[s_reload].secondary_out_reload == t_reload))
&& ((in_p && rld[s_reload].secondary_in_icode == t_icode)
|| (! in_p && rld[s_reload].secondary_out_icode == t_icode))
- && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
opnum, rld[s_reload].opnum))
{
@@ -573,7 +506,58 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
*picode = icode;
return s_reload;
}
-#endif /* HAVE_SECONDARY_RELOADS */
+
+/* If a secondary reload is needed, return its class. If both an intermediate
+ register and a scratch register is needed, we return the class of the
+ intermediate register. */
+enum reg_class
+secondary_reload_class (bool in_p, enum reg_class class,
+ enum machine_mode mode, rtx x)
+{
+ enum insn_code icode;
+ secondary_reload_info sri;
+
+ sri.icode = CODE_FOR_nothing;
+ sri.prev_sri = NULL;
+ class = targetm.secondary_reload (in_p, x, class, mode, &sri);
+ icode = sri.icode;
+
+ /* If there are no secondary reloads at all, we return NO_REGS.
+ If an intermediate register is needed, we return its class. */
+ if (icode == CODE_FOR_nothing || class != NO_REGS)
+ return class;
+
+ /* No intermediate register is needed, but we have a special reload
+ pattern, which we assume for now needs a scratch register. */
+ return scratch_reload_class (icode);
+}
+
+/* ICODE is the insn_code of a reload pattern. Check that it has exactly
+ three operands, verify that operand 2 is an output operand, and return
+ its register class.
+ ??? We'd like to be able to handle any pattern with at least 2 operands,
+ for zero or more scratch registers, but that needs more infrastructure. */
+enum reg_class
+scratch_reload_class (enum insn_code icode)
+{
+ const char *scratch_constraint;
+ char scratch_letter;
+ enum reg_class class;
+
+ gcc_assert (insn_data[(int) icode].n_operands == 3);
+ scratch_constraint = insn_data[(int) icode].operand[2].constraint;
+ gcc_assert (*scratch_constraint == '=');
+ scratch_constraint++;
+ if (*scratch_constraint == '&')
+ scratch_constraint++;
+ scratch_letter = *scratch_constraint;
+ if (scratch_letter == 'r')
+ return GENERAL_REGS;
+ class = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
+ scratch_constraint);
+ gcc_assert (class != NO_REGS);
+ return class;
+}
#ifdef SECONDARY_MEMORY_NEEDED
@@ -659,12 +643,15 @@ clear_secondary_mem (void)
}
#endif /* SECONDARY_MEMORY_NEEDED */
-/* Find the largest class for which every register number plus N is valid in
- M1 (if in range) and is cheap to move into REGNO.
- Abort if no such class exists. */
+
+/* Find the largest class which has at least one register valid in
+ mode INNER, and which for every such register, that register number
+ plus N is also valid in OUTER (if in range) and is cheap to move
+ into REGNO. Such a class must exist. */
static enum reg_class
-find_valid_class (enum machine_mode m1 ATTRIBUTE_UNUSED, int n,
+find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
+ enum machine_mode inner ATTRIBUTE_UNUSED, int n,
unsigned int dest_regno ATTRIBUTE_UNUSED)
{
int best_cost = -1;
@@ -678,15 +665,22 @@ find_valid_class (enum machine_mode m1 ATTRIBUTE_UNUSED, int n,
for (class = 1; class < N_REG_CLASSES; class++)
{
int bad = 0;
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER && ! bad; regno++)
- if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
- && TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
- && ! HARD_REGNO_MODE_OK (regno + n, m1))
- bad = 1;
+ int good = 0;
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER - n && ! bad; regno++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[class], regno))
+ {
+ if (HARD_REGNO_MODE_OK (regno, inner))
+ {
+ good = 1;
+ if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
+ || ! HARD_REGNO_MODE_OK (regno + n, outer))
+ bad = 1;
+ }
+ }
- if (bad)
+ if (bad || !good)
continue;
- cost = REGISTER_MOVE_COST (m1, class, dest_class);
+ cost = REGISTER_MOVE_COST (outer, class, dest_class);
if ((reg_class_size[class] > best_size
&& (best_cost < 0 || best_cost >= cost))
@@ -694,12 +688,11 @@ find_valid_class (enum machine_mode m1 ATTRIBUTE_UNUSED, int n,
{
best_class = class;
best_size = reg_class_size[class];
- best_cost = REGISTER_MOVE_COST (m1, class, dest_class);
+ best_cost = REGISTER_MOVE_COST (outer, class, dest_class);
}
}
- if (best_size == 0)
- abort ();
+ gcc_assert (best_size != 0);
return best_class;
}
@@ -745,7 +738,7 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
|| (out != 0 && MATCHES (rld[i].out, out)
&& (in == 0 || rld[i].in == 0 || MATCHES (rld[i].in, in))))
&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
- && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum))
return i;
@@ -763,20 +756,20 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
|| TEST_HARD_REG_BIT (reg_class_contents[(int) class],
true_regnum (rld[i].reg_rtx)))
&& out == 0 && rld[i].out == 0 && rld[i].in != 0
- && ((GET_CODE (in) == REG
- && GET_RTX_CLASS (GET_CODE (rld[i].in)) == 'a'
+ && ((REG_P (in)
+ && GET_RTX_CLASS (GET_CODE (rld[i].in)) == RTX_AUTOINC
&& MATCHES (XEXP (rld[i].in, 0), in))
- || (GET_CODE (rld[i].in) == REG
- && GET_RTX_CLASS (GET_CODE (in)) == 'a'
+ || (REG_P (rld[i].in)
+ && GET_RTX_CLASS (GET_CODE (in)) == RTX_AUTOINC
&& MATCHES (XEXP (in, 0), rld[i].in)))
&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
- && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (type, rld[i].when_needed,
opnum, rld[i].opnum))
{
/* Make sure reload_in ultimately has the increment,
not the plain register. */
- if (GET_CODE (in) == REG)
+ if (REG_P (in))
*p_in = rld[i].in;
return i;
}
@@ -803,7 +796,7 @@ reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
/* If INNER is not a hard register, then INNER will not need to
be reloaded. */
- if (GET_CODE (inner) != REG
+ if (!REG_P (inner)
|| REGNO (inner) >= FIRST_PSEUDO_REGISTER)
return 0;
@@ -818,7 +811,7 @@ reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
&& output
&& GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
&& ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
- != (int) HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
+ != (int) hard_regno_nregs[REGNO (inner)][GET_MODE (inner)]));
}
/* Return nonzero if IN can be reloaded into REGNO with mode MODE without
@@ -847,14 +840,14 @@ can_reload_into (rtx in, int regno, enum machine_mode mode)
technically this is a non-optional input-output reload, but IN is
already a valid register, and has been chosen as the reload register.
Speed this up, since it trivially works. */
- if (GET_CODE (in) == REG)
+ if (REG_P (in))
return 1;
/* To test MEMs properly, we'd have to take into account all the reloads
that are already scheduled, which can become quite complicated.
And since we've already handled address reloads for this MEM, it
should always succeed anyway. */
- if (GET_CODE (in) == MEM)
+ if (MEM_P (in))
return 1;
/* If we can make a simple SET insn that does the job, everything should
@@ -930,7 +923,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
it is not in a hard register, reload straight from the constant,
since we want to get rid of such pseudo registers.
Often this is done earlier, but not always in find_reloads_address. */
- if (in != 0 && GET_CODE (in) == REG)
+ if (in != 0 && REG_P (in))
{
int regno = REGNO (in);
@@ -942,7 +935,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/* Likewise for OUT. Of course, OUT will never be equivalent to
an actual constant, but it might be equivalent to a memory location
(in the case of a parameter). */
- if (out != 0 && GET_CODE (out) == REG)
+ if (out != 0 && REG_P (out))
{
int regno = REGNO (out);
@@ -953,7 +946,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/* If we have a read-write operand with an address side-effect,
change either IN or OUT so the side-effect happens only once. */
- if (in != 0 && out != 0 && GET_CODE (in) == MEM && rtx_equal_p (in, out))
+ if (in != 0 && out != 0 && MEM_P (in) && rtx_equal_p (in, out))
switch (GET_CODE (XEXP (in, 0)))
{
case POST_INC: case POST_DEC: case POST_MODIFY:
@@ -1006,9 +999,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
|| strict_low
- || (((GET_CODE (SUBREG_REG (in)) == REG
+ || (((REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
- || GET_CODE (SUBREG_REG (in)) == MEM)
+ || MEM_P (SUBREG_REG (in)))
&& ((GET_MODE_SIZE (inmode)
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
#ifdef LOAD_EXTEND_OP
@@ -1018,7 +1011,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
&& (GET_MODE_SIZE (inmode)
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
&& INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
- && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != NIL)
+ && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
#endif
#ifdef WORD_REGISTER_OPERATIONS
|| ((GET_MODE_SIZE (inmode)
@@ -1028,7 +1021,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/ UNITS_PER_WORD)))
#endif
))
- || (GET_CODE (SUBREG_REG (in)) == REG
+ || (REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
/* The case where out is nonzero
is handled differently in the following statement. */
@@ -1038,18 +1031,15 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
> UNITS_PER_WORD)
&& ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
/ UNITS_PER_WORD)
- != (int) HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
- GET_MODE (SUBREG_REG (in)))))
+ != (int) hard_regno_nregs[REGNO (SUBREG_REG (in))]
+ [GET_MODE (SUBREG_REG (in))]))
|| ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
- && (SECONDARY_INPUT_RELOAD_CLASS (class,
- GET_MODE (SUBREG_REG (in)),
- SUBREG_REG (in))
+ || (secondary_reload_class (1, class, inmode, in) != NO_REGS
+ && (secondary_reload_class (1, class, GET_MODE (SUBREG_REG (in)),
+ SUBREG_REG (in))
== NO_REGS))
-#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
- || (GET_CODE (SUBREG_REG (in)) == REG
+ || (REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P
(REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
@@ -1060,11 +1050,10 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
inloc = &SUBREG_REG (in);
in = *inloc;
#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
- if (GET_CODE (in) == MEM)
+ if (MEM_P (in))
/* This is supposed to happen only for paradoxical subregs made by
combine.c. (SUBREG (MEM)) isn't supposed to occur other ways. */
- if (GET_MODE_SIZE (GET_MODE (in)) > GET_MODE_SIZE (inmode))
- abort ();
+ gcc_assert (GET_MODE_SIZE (GET_MODE (in)) <= GET_MODE_SIZE (inmode));
#endif
inmode = GET_MODE (in);
}
@@ -1083,9 +1072,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
{
enum reg_class in_class = class;
- if (GET_CODE (SUBREG_REG (in)) == REG)
+ if (REG_P (SUBREG_REG (in)))
in_class
- = find_valid_class (inmode,
+ = find_valid_class (inmode, GET_MODE (SUBREG_REG (in)),
subreg_regno_offset (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)),
SUBREG_BYTE (in),
@@ -1115,9 +1104,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
#endif
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
- || (((GET_CODE (SUBREG_REG (out)) == REG
+ || (((REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
- || GET_CODE (SUBREG_REG (out)) == MEM)
+ || MEM_P (SUBREG_REG (out)))
&& ((GET_MODE_SIZE (outmode)
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
#ifdef WORD_REGISTER_OPERATIONS
@@ -1128,25 +1117,22 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/ UNITS_PER_WORD)))
#endif
))
- || (GET_CODE (SUBREG_REG (out)) == REG
+ || (REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
> UNITS_PER_WORD)
&& ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
/ UNITS_PER_WORD)
- != (int) HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
- GET_MODE (SUBREG_REG (out)))))
+ != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
+ [GET_MODE (SUBREG_REG (out))]))
|| ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
- && (SECONDARY_OUTPUT_RELOAD_CLASS (class,
- GET_MODE (SUBREG_REG (out)),
- SUBREG_REG (out))
+ || (secondary_reload_class (0, class, outmode, out) != NO_REGS
+ && (secondary_reload_class (0, class, GET_MODE (SUBREG_REG (out)),
+ SUBREG_REG (out))
== NO_REGS))
-#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
- || (GET_CODE (SUBREG_REG (out)) == REG
+ || (REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
@@ -1158,9 +1144,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
outloc = &SUBREG_REG (out);
out = *outloc;
#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
- if (GET_CODE (out) == MEM
- && GET_MODE_SIZE (GET_MODE (out)) > GET_MODE_SIZE (outmode))
- abort ();
+ gcc_assert (!MEM_P (out)
+ || GET_MODE_SIZE (GET_MODE (out))
+ <= GET_MODE_SIZE (outmode));
#endif
outmode = GET_MODE (out);
}
@@ -1182,7 +1168,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
&SUBREG_REG (out),
- find_valid_class (outmode,
+ find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
subreg_regno_offset (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
SUBREG_BYTE (out),
@@ -1193,37 +1179,46 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
}
/* If IN appears in OUT, we can't share any input-only reload for IN. */
- if (in != 0 && out != 0 && GET_CODE (out) == MEM
- && (GET_CODE (in) == REG || GET_CODE (in) == MEM)
+ if (in != 0 && out != 0 && MEM_P (out)
+ && (REG_P (in) || MEM_P (in))
&& reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
dont_share = 1;
/* If IN is a SUBREG of a hard register, make a new REG. This
simplifies some of the cases below. */
- if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
+ if (in != 0 && GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& ! dont_remove_subreg)
in = gen_rtx_REG (GET_MODE (in), subreg_regno (in));
/* Similarly for OUT. */
if (out != 0 && GET_CODE (out) == SUBREG
- && GET_CODE (SUBREG_REG (out)) == REG
+ && REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& ! dont_remove_subreg)
out = gen_rtx_REG (GET_MODE (out), subreg_regno (out));
/* Narrow down the class of register wanted if that is
desirable on this machine for efficiency. */
- if (in != 0)
- class = PREFERRED_RELOAD_CLASS (in, class);
+ {
+ enum reg_class preferred_class = class;
+
+ if (in != 0)
+ preferred_class = PREFERRED_RELOAD_CLASS (in, class);
/* Output reloads may need analogous treatment, different in detail. */
#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
- if (out != 0)
- class = PREFERRED_OUTPUT_RELOAD_CLASS (out, class);
+ if (out != 0)
+ preferred_class = PREFERRED_OUTPUT_RELOAD_CLASS (out, preferred_class);
#endif
+ /* Discard what the target said if we cannot do it. */
+ if (preferred_class != NO_REGS
+ || (optional && type == RELOAD_FOR_OUTPUT))
+ class = preferred_class;
+ }
+
/* Make sure we use a class that can handle the actual pseudo
inside any subreg. For example, on the 386, QImode regs
can appear within SImode subregs. Although GENERAL_REGS
@@ -1251,7 +1246,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
mode = outmode;
if (mode == VOIDmode)
{
- error_for_asm (this_insn, "cannot reload integer constant operand in `asm'");
+ error_for_asm (this_insn, "cannot reload integer constant "
+ "operand in %<asm%>");
mode = word_mode;
if (in != 0)
inmode = word_mode;
@@ -1262,7 +1258,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
if (HARD_REGNO_MODE_OK (i, mode)
&& TEST_HARD_REG_BIT (reg_class_contents[(int) class], i))
{
- int nregs = HARD_REGNO_NREGS (i, mode);
+ int nregs = hard_regno_nregs[i][mode];
int j;
for (j = 1; j < nregs; j++)
@@ -1273,17 +1269,29 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
}
if (i == FIRST_PSEUDO_REGISTER)
{
- error_for_asm (this_insn, "impossible register constraint in `asm'");
- class = ALL_REGS;
+ error_for_asm (this_insn, "impossible register constraint "
+ "in %<asm%>");
+ /* Avoid further trouble with this insn. */
+ PATTERN (this_insn) = gen_rtx_USE (VOIDmode, const0_rtx);
+ /* We used to continue here setting class to ALL_REGS, but it triggers
+ sanity check on i386 for:
+ void foo(long double d)
+ {
+ asm("" :: "a" (d));
+ }
+ Returning zero here ought to be safe as we take care in
+ find_reloads to not process the reloads when instruction was
+ replaced by USE. */
+
+ return 0;
}
}
/* Optional output reloads are always OK even if we have no register class,
since the function of these reloads is only to have spill_reg_store etc.
set, so that the storing insn can be deleted later. */
- if (class == NO_REGS
- && (optional == 0 || type != RELOAD_FOR_OUTPUT))
- abort ();
+ gcc_assert (class != NO_REGS
+ || (optional != 0 && type == RELOAD_FOR_OUTPUT));
i = find_reusable_reload (&in, out, class, type, opnum, dont_share);
@@ -1293,26 +1301,23 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
and IN or CLASS and OUT. Get the icode and push any required reloads
needed for each of them if so. */
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
if (in != 0)
secondary_in_reload
= push_secondary_reload (1, in, opnum, optional, class, inmode, type,
- &secondary_in_icode);
-#endif
-
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+ &secondary_in_icode, NULL);
if (out != 0 && GET_CODE (out) != SCRATCH)
secondary_out_reload
= push_secondary_reload (0, out, opnum, optional, class, outmode,
- type, &secondary_out_icode);
-#endif
+ type, &secondary_out_icode, NULL);
/* We found no existing reload suitable for re-use.
So add an additional reload. */
#ifdef SECONDARY_MEMORY_NEEDED
/* If a memory location is needed for the copy, make one. */
- if (in != 0 && (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
+ if (in != 0
+ && (REG_P (in)
+ || (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
&& reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
class, inmode))
@@ -1342,7 +1347,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
n_reloads++;
#ifdef SECONDARY_MEMORY_NEEDED
- if (out != 0 && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG)
+ if (out != 0
+ && (REG_P (out)
+ || (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
&& reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (class,
REGNO_REG_CLASS (reg_or_subregno (out)),
@@ -1437,8 +1444,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/* If we did not find a nonzero amount-to-increment-by,
that contradicts the belief that IN is being incremented
in an address in this insn. */
- if (rld[i].inc == 0)
- abort ();
+ gcc_assert (rld[i].inc != 0);
}
#endif
@@ -1486,7 +1492,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
The easiest way to tell the caller that is to give a phony
value for the incoming operand (same as outgoing one). */
if (rld[i].reg_rtx == out
- && (GET_CODE (in) == REG || CONSTANT_P (in))
+ && (REG_P (in) || CONSTANT_P (in))
&& 0 != find_equiv_reg (in, this_insn, 0, REGNO (out),
static_reload_reg_p, i, inmode))
rld[i].in = out;
@@ -1504,7 +1510,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
But if there is no spilling in this block, that is OK.
An explicitly used hard reg cannot be a spill reg. */
- if (rld[i].reg_rtx == 0 && in != 0)
+ if (rld[i].reg_rtx == 0 && in != 0 && hard_regs_live_known)
{
rtx note;
int regno;
@@ -1515,13 +1521,18 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_DEAD
- && GET_CODE (XEXP (note, 0)) == REG
+ && REG_P (XEXP (note, 0))
&& (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER
&& reg_mentioned_p (XEXP (note, 0), in)
+ /* Check that we don't use a hardreg for an uninitialized
+ pseudo. See also find_dummy_reload(). */
+ && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
+ || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
+ ORIGINAL_REGNO (XEXP (note, 0))))
&& ! refers_to_regno_for_reload_p (regno,
(regno
- + HARD_REGNO_NREGS (regno,
- rel_mode)),
+ + hard_regno_nregs[regno]
+ [rel_mode]),
PATTERN (this_insn), inloc)
/* If this is also an output reload, IN cannot be used as
the reload register if it is set in this insn unless IN
@@ -1529,8 +1540,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
&& (out == 0 || in == out
|| ! hard_reg_set_here_p (regno,
(regno
- + HARD_REGNO_NREGS (regno,
- rel_mode)),
+ + hard_regno_nregs[regno]
+ [rel_mode]),
PATTERN (this_insn)))
/* ??? Why is this code so different from the previous?
Is there any simple coherent way to describe the two together?
@@ -1548,8 +1559,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
&& HARD_REGNO_MODE_OK (regno, outmode))
{
unsigned int offs;
- unsigned int nregs = MAX (HARD_REGNO_NREGS (regno, inmode),
- HARD_REGNO_NREGS (regno, outmode));
+ unsigned int nregs = MAX (hard_regno_nregs[regno][inmode],
+ hard_regno_nregs[regno][outmode]);
for (offs = 0; offs < nregs; offs++)
if (fixed_regs[regno + offs]
@@ -1559,7 +1570,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
if (offs == nregs
&& (! (refers_to_regno_for_reload_p
- (regno, (regno + HARD_REGNO_NREGS (regno, inmode)),
+ (regno, (regno + hard_regno_nregs[regno][inmode]),
in, (rtx *)0))
|| can_reload_into (in, regno, inmode)))
{
@@ -1754,7 +1765,7 @@ combine_reloads (void)
If the same reload reg is used for both reg 69 and the
result to be stored in memory, then that result
will clobber the address of the memory ref. */
- && ! (GET_CODE (rld[i].in) == REG
+ && ! (REG_P (rld[i].in)
&& reg_overlap_mentioned_for_reload_p (rld[i].in,
rld[output_reload].out))))
&& ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
@@ -1823,15 +1834,15 @@ combine_reloads (void)
up can fully hold our output reload. */
for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_DEAD
- && GET_CODE (XEXP (note, 0)) == REG
+ && REG_P (XEXP (note, 0))
&& ! reg_overlap_mentioned_for_reload_p (XEXP (note, 0),
rld[output_reload].out)
&& REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
&& HARD_REGNO_MODE_OK (REGNO (XEXP (note, 0)), rld[output_reload].outmode)
&& TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].class],
REGNO (XEXP (note, 0)))
- && (HARD_REGNO_NREGS (REGNO (XEXP (note, 0)), rld[output_reload].outmode)
- <= HARD_REGNO_NREGS (REGNO (XEXP (note, 0)), GET_MODE (XEXP (note, 0))))
+ && (hard_regno_nregs[REGNO (XEXP (note, 0))][rld[output_reload].outmode]
+ <= hard_regno_nregs[REGNO (XEXP (note, 0))][GET_MODE (XEXP (note, 0))])
/* Ensure that a secondary or tertiary reload for this output
won't want this register. */
&& ((secondary_out = rld[output_reload].secondary_out_reload) == -1
@@ -1842,7 +1853,12 @@ combine_reloads (void)
|| ! (TEST_HARD_REG_BIT
(reg_class_contents[(int) rld[secondary_out].class],
REGNO (XEXP (note, 0)))))))
- && ! fixed_regs[REGNO (XEXP (note, 0))])
+ && ! fixed_regs[REGNO (XEXP (note, 0))]
+ /* Check that we don't use a hardreg for an uninitialized
+ pseudo. See also find_dummy_reload(). */
+ && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
+ || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
+ ORIGINAL_REGNO (XEXP (note, 0)))))
{
rld[output_reload].reg_rtx
= gen_rtx_REG (rld[output_reload].outmode,
@@ -1895,7 +1911,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
/* Find the inside of any subregs. */
while (GET_CODE (out) == SUBREG)
{
- if (GET_CODE (SUBREG_REG (out)) == REG
+ if (REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
out_offset += subreg_regno_offset (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
@@ -1905,7 +1921,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
}
while (GET_CODE (in) == SUBREG)
{
- if (GET_CODE (SUBREG_REG (in)) == REG
+ if (REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
in_offset += subreg_regno_offset (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)),
@@ -1916,14 +1932,18 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
/* Narrow down the reg class, the same way push_reload will;
otherwise we might find a dummy now, but push_reload won't. */
- class = PREFERRED_RELOAD_CLASS (in, class);
+ {
+ enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, class);
+ if (preferred_class != NO_REGS)
+ class = preferred_class;
+ }
/* See if OUT will do. */
- if (GET_CODE (out) == REG
+ if (REG_P (out)
&& REGNO (out) < FIRST_PSEUDO_REGISTER)
{
unsigned int regno = REGNO (out) + out_offset;
- unsigned int nwords = HARD_REGNO_NREGS (regno, outmode);
+ unsigned int nwords = hard_regno_nregs[regno][outmode];
rtx saved_rtx;
/* When we consider whether the insn uses OUT,
@@ -1952,7 +1972,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
if (i == nwords)
{
- if (GET_CODE (real_out) == REG)
+ if (REG_P (real_out))
value = real_out;
else
value = gen_rtx_REG (outmode, regno);
@@ -1969,7 +1989,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
Also, the result can't go in IN if IN is used within OUT,
or if OUT is an earlyclobber and IN appears elsewhere in the insn. */
if (hard_regs_live_known
- && GET_CODE (in) == REG
+ && REG_P (in)
&& REGNO (in) < FIRST_PSEUDO_REGISTER
&& (value == 0
|| find_reg_note (this_insn, REG_UNUSED, real_out))
@@ -1981,10 +2001,20 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
is a subreg, and in that case, out
has a real mode. */
(GET_MODE (out) != VOIDmode
- ? GET_MODE (out) : outmode)))
+ ? GET_MODE (out) : outmode))
+ /* But only do all this if we can be sure, that this input
+ operand doesn't correspond with an uninitialized pseudoreg.
+ global can assign some hardreg to it, which is the same as
+ a different pseudo also currently live (as it can ignore the
+ conflict). So we never must introduce writes to such hardregs,
+ as they would clobber the other live pseudo using the same.
+ See also PR20973. */
+ && (ORIGINAL_REGNO (in) < FIRST_PSEUDO_REGISTER
+ || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
+ ORIGINAL_REGNO (in))))
{
unsigned int regno = REGNO (in) + in_offset;
- unsigned int nwords = HARD_REGNO_NREGS (regno, inmode);
+ unsigned int nwords = hard_regno_nregs[regno][inmode];
if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, (rtx*) 0)
&& ! hard_reg_set_here_p (regno, regno + nwords,
@@ -2007,7 +2037,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
dies here. So don't bother copying value to it. */
if (for_real >= 0 && value == real_out)
rld[for_real].out = 0;
- if (GET_CODE (real_in) == REG)
+ if (REG_P (real_in))
value = real_in;
else
value = gen_rtx_REG (inmode, regno);
@@ -2050,13 +2080,13 @@ hard_reg_set_here_p (unsigned int beg_regno, unsigned int end_regno, rtx x)
while (GET_CODE (op0) == SUBREG)
op0 = SUBREG_REG (op0);
- if (GET_CODE (op0) == REG)
+ if (REG_P (op0))
{
unsigned int r = REGNO (op0);
/* See if this reg overlaps range under consideration. */
if (r < end_regno
- && r + HARD_REGNO_NREGS (r, GET_MODE (op0)) > beg_regno)
+ && r + hard_regno_nregs[r][GET_MODE (op0)] > beg_regno)
return 1;
}
}
@@ -2111,9 +2141,9 @@ operands_match_p (rtx x, rtx y)
if (x == y)
return 1;
- if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
- && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG
- && GET_CODE (SUBREG_REG (y)) == REG)))
+ if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x))))
+ && (REG_P (y) || (GET_CODE (y) == SUBREG
+ && REG_P (SUBREG_REG (y)))))
{
int j;
@@ -2150,11 +2180,11 @@ operands_match_p (rtx x, rtx y)
if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
&& SCALAR_INT_MODE_P (GET_MODE (x))
&& i < FIRST_PSEUDO_REGISTER)
- i += HARD_REGNO_NREGS (i, GET_MODE (x)) - 1;
+ i += hard_regno_nregs[i][GET_MODE (x)] - 1;
if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
&& SCALAR_INT_MODE_P (GET_MODE (y))
&& j < FIRST_PSEUDO_REGISTER)
- j += HARD_REGNO_NREGS (j, GET_MODE (y)) - 1;
+ j += hard_regno_nregs[j][GET_MODE (y)] - 1;
return i == j;
}
@@ -2177,20 +2207,30 @@ operands_match_p (rtx x, rtx y)
slow:
- /* Now we have disposed of all the cases
- in which different rtx codes can match. */
+ /* Now we have disposed of all the cases in which different rtx codes
+ can match. */
if (code != GET_CODE (y))
return 0;
- if (code == LABEL_REF)
- return XEXP (x, 0) == XEXP (y, 0);
- if (code == SYMBOL_REF)
- return XSTR (x, 0) == XSTR (y, 0);
/* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */
-
if (GET_MODE (x) != GET_MODE (y))
return 0;
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ return 0;
+
+ case LABEL_REF:
+ return XEXP (x, 0) == XEXP (y, 0);
+ case SYMBOL_REF:
+ return XSTR (x, 0) == XSTR (y, 0);
+
+ default:
+ break;
+ }
+
/* Compare the elements. If any pair of corresponding elements
fail to match, return 0 for the whole things. */
@@ -2241,7 +2281,7 @@ operands_match_p (rtx x, rtx y)
contain anything but integers and other rtx's,
except for within LABEL_REFs and SYMBOL_REFs. */
default:
- abort ();
+ gcc_unreachable ();
}
}
return 1 + success_2;
@@ -2261,104 +2301,104 @@ decompose (rtx x)
struct decomposition val;
int all_const = 0;
- val.reg_flag = 0;
- val.safe = 0;
- val.base = 0;
- if (GET_CODE (x) == MEM)
- {
- rtx base = NULL_RTX, offset = 0;
- rtx addr = XEXP (x, 0);
-
- if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
- || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
- {
- val.base = XEXP (addr, 0);
- val.start = -GET_MODE_SIZE (GET_MODE (x));
- val.end = GET_MODE_SIZE (GET_MODE (x));
- val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
- return val;
- }
-
- if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
- {
- if (GET_CODE (XEXP (addr, 1)) == PLUS
- && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
- && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
- {
- val.base = XEXP (addr, 0);
- val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
- val.end = INTVAL (XEXP (XEXP (addr, 1), 1));
- val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
- return val;
- }
- }
-
- if (GET_CODE (addr) == CONST)
- {
- addr = XEXP (addr, 0);
- all_const = 1;
- }
- if (GET_CODE (addr) == PLUS)
- {
- if (CONSTANT_P (XEXP (addr, 0)))
- {
- base = XEXP (addr, 1);
- offset = XEXP (addr, 0);
- }
- else if (CONSTANT_P (XEXP (addr, 1)))
- {
- base = XEXP (addr, 0);
- offset = XEXP (addr, 1);
- }
- }
+ memset (&val, 0, sizeof (val));
- if (offset == 0)
- {
- base = addr;
- offset = const0_rtx;
- }
- if (GET_CODE (offset) == CONST)
- offset = XEXP (offset, 0);
- if (GET_CODE (offset) == PLUS)
- {
- if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
- {
- base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
- offset = XEXP (offset, 0);
- }
- else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
- {
- base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
- offset = XEXP (offset, 1);
- }
- else
- {
- base = gen_rtx_PLUS (GET_MODE (base), base, offset);
- offset = const0_rtx;
- }
- }
- else if (GET_CODE (offset) != CONST_INT)
- {
- base = gen_rtx_PLUS (GET_MODE (base), base, offset);
- offset = const0_rtx;
- }
-
- if (all_const && GET_CODE (base) == PLUS)
- base = gen_rtx_CONST (GET_MODE (base), base);
-
- if (GET_CODE (offset) != CONST_INT)
- abort ();
-
- val.start = INTVAL (offset);
- val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
- val.base = base;
- return val;
- }
- else if (GET_CODE (x) == REG)
+ switch (GET_CODE (x))
{
+ case MEM:
+ {
+ rtx base = NULL_RTX, offset = 0;
+ rtx addr = XEXP (x, 0);
+
+ if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
+ || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
+ {
+ val.base = XEXP (addr, 0);
+ val.start = -GET_MODE_SIZE (GET_MODE (x));
+ val.end = GET_MODE_SIZE (GET_MODE (x));
+ val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
+ return val;
+ }
+
+ if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
+ {
+ if (GET_CODE (XEXP (addr, 1)) == PLUS
+ && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
+ && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
+ {
+ val.base = XEXP (addr, 0);
+ val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
+ val.end = INTVAL (XEXP (XEXP (addr, 1), 1));
+ val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
+ return val;
+ }
+ }
+
+ if (GET_CODE (addr) == CONST)
+ {
+ addr = XEXP (addr, 0);
+ all_const = 1;
+ }
+ if (GET_CODE (addr) == PLUS)
+ {
+ if (CONSTANT_P (XEXP (addr, 0)))
+ {
+ base = XEXP (addr, 1);
+ offset = XEXP (addr, 0);
+ }
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ {
+ base = XEXP (addr, 0);
+ offset = XEXP (addr, 1);
+ }
+ }
+
+ if (offset == 0)
+ {
+ base = addr;
+ offset = const0_rtx;
+ }
+ if (GET_CODE (offset) == CONST)
+ offset = XEXP (offset, 0);
+ if (GET_CODE (offset) == PLUS)
+ {
+ if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
+ {
+ base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
+ offset = XEXP (offset, 0);
+ }
+ else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
+ {
+ base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
+ offset = XEXP (offset, 1);
+ }
+ else
+ {
+ base = gen_rtx_PLUS (GET_MODE (base), base, offset);
+ offset = const0_rtx;
+ }
+ }
+ else if (GET_CODE (offset) != CONST_INT)
+ {
+ base = gen_rtx_PLUS (GET_MODE (base), base, offset);
+ offset = const0_rtx;
+ }
+
+ if (all_const && GET_CODE (base) == PLUS)
+ base = gen_rtx_CONST (GET_MODE (base), base);
+
+ gcc_assert (GET_CODE (offset) == CONST_INT);
+
+ val.start = INTVAL (offset);
+ val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
+ val.base = base;
+ }
+ break;
+
+ case REG:
val.reg_flag = 1;
val.start = true_regnum (x);
- if (val.start < 0)
+ if (val.start < 0 || val.start >= FIRST_PSEUDO_REGISTER)
{
/* A pseudo with no hard reg. */
val.start = REGNO (x);
@@ -2366,27 +2406,32 @@ decompose (rtx x)
}
else
/* A hard reg. */
- val.end = val.start + HARD_REGNO_NREGS (val.start, GET_MODE (x));
- }
- else if (GET_CODE (x) == SUBREG)
- {
- if (GET_CODE (SUBREG_REG (x)) != REG)
+ val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+ break;
+
+ case SUBREG:
+ if (!REG_P (SUBREG_REG (x)))
/* This could be more precise, but it's good enough. */
return decompose (SUBREG_REG (x));
val.reg_flag = 1;
val.start = true_regnum (x);
- if (val.start < 0)
+ if (val.start < 0 || val.start >= FIRST_PSEUDO_REGISTER)
return decompose (SUBREG_REG (x));
else
/* A hard reg. */
- val.end = val.start + HARD_REGNO_NREGS (val.start, GET_MODE (x));
+ val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+ break;
+
+ case SCRATCH:
+ /* This hasn't been assigned yet, so it can't conflict yet. */
+ val.safe = 1;
+ break;
+
+ default:
+ gcc_assert (CONSTANT_P (x));
+ val.safe = 1;
+ break;
}
- else if (CONSTANT_P (x)
- /* This hasn't been assigned yet, so it can't conflict yet. */
- || GET_CODE (x) == SCRATCH)
- val.safe = 1;
- else
- abort ();
return val;
}
@@ -2403,10 +2448,9 @@ immune_p (rtx x, rtx y, struct decomposition ydata)
if (ydata.safe)
return 1;
- if (GET_CODE (y) != MEM)
- abort ();
+ gcc_assert (MEM_P (y));
/* If Y is memory and X is not, Y can't affect X. */
- if (GET_CODE (x) != MEM)
+ if (!MEM_P (x))
return 1;
xdata = decompose (x);
@@ -2481,9 +2525,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
a register. */
enum reg_class preferred_class[MAX_RECOG_OPERANDS];
char pref_or_nothing[MAX_RECOG_OPERANDS];
- /* Nonzero for a MEM operand whose entire address needs a reload. */
+ /* Nonzero for a MEM operand whose entire address needs a reload.
+ May be -1 to indicate the entire address may or may not need a reload. */
int address_reloaded[MAX_RECOG_OPERANDS];
- /* Nonzero for an address operand that needs to be completely reloaded. */
+ /* Nonzero for an address operand that needs to be completely reloaded.
+ May be -1 to indicate the entire operand may or may not need a reload. */
int address_operand_reloaded[MAX_RECOG_OPERANDS];
/* Value of enum reload_type to use for operand. */
enum reload_type operand_type[MAX_RECOG_OPERANDS];
@@ -2532,7 +2578,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* JUMP_INSNs and CALL_INSNs are not allowed to have any output reloads;
neither are insns that SET cc0. Insns that use CC0 are not allowed
to have any input reloads. */
- if (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN)
+ if (JUMP_P (insn) || CALL_P (insn))
no_output_reloads = 1;
#ifdef HAVE_cc0
@@ -2558,9 +2604,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
is cheap to move between them. If it is not, there may not be an insn
to do the copy, so we may need a reload. */
if (GET_CODE (body) == SET
- && GET_CODE (SET_DEST (body)) == REG
+ && REG_P (SET_DEST (body))
&& REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
- && GET_CODE (SET_SRC (body)) == REG
+ && REG_P (SET_SRC (body))
&& REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
&& REGISTER_MOVE_COST (GET_MODE (SET_SRC (body)),
REGNO_REG_CLASS (REGNO (SET_SRC (body))),
@@ -2606,62 +2652,69 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
while ((c = *p))
{
p += CONSTRAINT_LEN (c, p);
- if (c == '=')
- modified[i] = RELOAD_WRITE;
- else if (c == '+')
- modified[i] = RELOAD_READ_WRITE;
- else if (c == '%')
- {
- /* The last operand should not be marked commutative. */
- if (i == noperands - 1)
- abort ();
-
- /* We currently only support one commutative pair of
- operands. Some existing asm code currently uses more
- than one pair. Previously, that would usually work,
- but sometimes it would crash the compiler. We
- continue supporting that case as well as we can by
- silently ignoring all but the first pair. In the
- future we may handle it correctly. */
- if (commutative < 0)
- commutative = i;
- else if (!this_insn_is_asm)
- abort ();
- }
- else if (ISDIGIT (c))
+ switch (c)
{
- c = strtoul (p - 1, &p, 10);
+ case '=':
+ modified[i] = RELOAD_WRITE;
+ break;
+ case '+':
+ modified[i] = RELOAD_READ_WRITE;
+ break;
+ case '%':
+ {
+ /* The last operand should not be marked commutative. */
+ gcc_assert (i != noperands - 1);
+
+ /* We currently only support one commutative pair of
+ operands. Some existing asm code currently uses more
+ than one pair. Previously, that would usually work,
+ but sometimes it would crash the compiler. We
+ continue supporting that case as well as we can by
+ silently ignoring all but the first pair. In the
+ future we may handle it correctly. */
+ if (commutative < 0)
+ commutative = i;
+ else
+ gcc_assert (this_insn_is_asm);
+ }
+ break;
+ /* Use of ISDIGIT is tempting here, but it may get expensive because
+ of locale support we don't want. */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ c = strtoul (p - 1, &p, 10);
- operands_match[c][i]
- = operands_match_p (recog_data.operand[c],
- recog_data.operand[i]);
+ operands_match[c][i]
+ = operands_match_p (recog_data.operand[c],
+ recog_data.operand[i]);
- /* An operand may not match itself. */
- if (c == i)
- abort ();
+ /* An operand may not match itself. */
+ gcc_assert (c != i);
- /* If C can be commuted with C+1, and C might need to match I,
- then C+1 might also need to match I. */
- if (commutative >= 0)
- {
- if (c == commutative || c == commutative + 1)
- {
- int other = c + (c == commutative ? 1 : -1);
- operands_match[other][i]
- = operands_match_p (recog_data.operand[other],
- recog_data.operand[i]);
- }
- if (i == commutative || i == commutative + 1)
- {
- int other = i + (i == commutative ? 1 : -1);
- operands_match[c][other]
- = operands_match_p (recog_data.operand[c],
- recog_data.operand[other]);
- }
- /* Note that C is supposed to be less than I.
- No need to consider altering both C and I because in
- that case we would alter one into the other. */
- }
+ /* If C can be commuted with C+1, and C might need to match I,
+ then C+1 might also need to match I. */
+ if (commutative >= 0)
+ {
+ if (c == commutative || c == commutative + 1)
+ {
+ int other = c + (c == commutative ? 1 : -1);
+ operands_match[other][i]
+ = operands_match_p (recog_data.operand[other],
+ recog_data.operand[i]);
+ }
+ if (i == commutative || i == commutative + 1)
+ {
+ int other = i + (i == commutative ? 1 : -1);
+ operands_match[c][other]
+ = operands_match_p (recog_data.operand[c],
+ recog_data.operand[other]);
+ }
+ /* Note that C is supposed to be less than I.
+ No need to consider altering both C and I because in
+ that case we would alter one into the other. */
+ }
+ }
}
}
}
@@ -2702,7 +2755,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* If we now have a simple operand where we used to have a
PLUS or MULT, re-recognize and try again. */
- if ((GET_RTX_CLASS (GET_CODE (*recog_data.operand_loc[i])) == 'o'
+ if ((OBJECT_P (*recog_data.operand_loc[i])
|| GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
&& (GET_CODE (recog_data.operand[i]) == MULT
|| GET_CODE (recog_data.operand[i]) == PLUS))
@@ -2748,8 +2801,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
wider reload. */
if (replace
- && GET_CODE (op) == MEM
- && GET_CODE (reg) == REG
+ && MEM_P (op)
+ && REG_P (reg)
&& (GET_MODE_SIZE (GET_MODE (reg))
>= GET_MODE_SIZE (GET_MODE (op))))
set_unique_reg_note (emit_insn_before (gen_rtx_USE (VOIDmode, reg),
@@ -2758,7 +2811,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
substed_operand[i] = recog_data.operand[i] = op;
}
- else if (code == PLUS || GET_RTX_CLASS (code) == '1')
+ else if (code == PLUS || GET_RTX_CLASS (code) == RTX_UNARY)
/* We can get a PLUS as an "operand" as a result of register
elimination. See eliminate_regs and gen_reload. We handle
a unary operator by reloading the operand. */
@@ -2886,7 +2939,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* If the predicate accepts a unary operator, it means that
we need to reload the operand, but do not do this for
match_operator and friends. */
- if (GET_RTX_CLASS (GET_CODE (operand)) == '1' && *p != 0)
+ if (UNARY_P (operand) && *p != 0)
operand = XEXP (operand, 0);
/* If the operand is a SUBREG, extract
@@ -2899,7 +2952,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
it is a hard reg. This is because it is passed
to reg_fits_class_p if it is a REG and all pseudos
return 0 from that function. */
- if (GET_CODE (SUBREG_REG (operand)) == REG
+ if (REG_P (SUBREG_REG (operand))
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
if (!subreg_offset_representable_p
@@ -2942,8 +2995,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
??? When is it right at this stage to have a subreg
of a mem that is _not_ to be handled specially? IMO
those should have been reduced to just a mem. */
- || ((GET_CODE (operand) == MEM
- || (GET_CODE (operand)== REG
+ || ((MEM_P (operand)
+ || (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
#ifndef WORD_REGISTER_OPERATIONS
&& (((GET_MODE_BITSIZE (GET_MODE (operand))
@@ -2958,7 +3011,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
&& (GET_MODE_SIZE (operand_mode[i])
> GET_MODE_SIZE (GET_MODE (operand)))
&& INTEGRAL_MODE_P (GET_MODE (operand))
- && LOAD_EXTEND_OP (GET_MODE (operand)) != NIL)
+ && LOAD_EXTEND_OP (GET_MODE (operand)) != UNKNOWN)
#endif
)
#endif
@@ -3053,7 +3106,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
offsettable address was expected, then we must reject
this combination, because we can't reload it. */
if (this_alternative_offmemok[m]
- && GET_CODE (recog_data.operand[m]) == MEM
+ && MEM_P (recog_data.operand[m])
&& this_alternative[m] == (int) NO_REGS
&& ! this_alternative_win[m])
bad = 1;
@@ -3119,7 +3172,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
case 'p':
/* All necessary reloads for an address_operand
were handled in find_reloads_address. */
- this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
+ this_alternative[i]
+ = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
win = 1;
badop = 0;
break;
@@ -3127,20 +3181,18 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
case 'm':
if (force_reload)
break;
- if (GET_CODE (operand) == MEM
- || (GET_CODE (operand) == REG
+ if (MEM_P (operand)
+ || (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0))
win = 1;
- if (CONSTANT_P (operand)
- /* force_const_mem does not accept HIGH. */
- && GET_CODE (operand) != HIGH)
+ if (CONST_POOL_OK_P (operand))
badop = 0;
constmemok = 1;
break;
case '<':
- if (GET_CODE (operand) == MEM
+ if (MEM_P (operand)
&& ! address_reloaded[i]
&& (GET_CODE (XEXP (operand, 0)) == PRE_DEC
|| GET_CODE (XEXP (operand, 0)) == POST_DEC))
@@ -3148,7 +3200,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
break;
case '>':
- if (GET_CODE (operand) == MEM
+ if (MEM_P (operand)
&& ! address_reloaded[i]
&& (GET_CODE (XEXP (operand, 0)) == PRE_INC
|| GET_CODE (XEXP (operand, 0)) == POST_INC))
@@ -3159,14 +3211,14 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
case 'V':
if (force_reload)
break;
- if (GET_CODE (operand) == MEM
+ if (MEM_P (operand)
&& ! (ind_levels ? offsettable_memref_p (operand)
: offsettable_nonstrict_memref_p (operand))
/* Certain mem addresses will become offsettable
after they themselves are reloaded. This is important;
we don't want our own handling of unoffsettables
to override the handling of reg_equiv_address. */
- && !(GET_CODE (XEXP (operand, 0)) == REG
+ && !(REG_P (XEXP (operand, 0))
&& (ind_levels == 0
|| reg_equiv_address[REGNO (XEXP (operand, 0))] != 0)))
win = 1;
@@ -3176,7 +3228,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
case 'o':
if (force_reload)
break;
- if ((GET_CODE (operand) == MEM
+ if ((MEM_P (operand)
/* If IND_LEVELS, find_reloads_address won't reload a
pseudo that didn't get a hard reg, so we have to
reject that case. */
@@ -3184,8 +3236,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
: offsettable_nonstrict_memref_p (operand))
/* A reloaded address is offsettable because it is now
just a simple register indirect. */
- || address_reloaded[i]))
- || (GET_CODE (operand) == REG
+ || address_reloaded[i] == 1))
+ || (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
/* If reg_equiv_address is nonzero, we will be
@@ -3196,9 +3248,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
&& offsettable_memref_p (reg_equiv_mem[REGNO (operand)]))
|| (reg_equiv_address[REGNO (operand)] != 0))))
win = 1;
- /* force_const_mem does not accept HIGH. */
- if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
- || GET_CODE (operand) == MEM)
+ if (CONST_POOL_OK_P (operand)
+ || MEM_P (operand))
badop = 0;
constmemok = 1;
offmemok = 1;
@@ -3233,10 +3284,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
break;
case 'i':
if (CONSTANT_P (operand)
-#ifdef LEGITIMATE_PIC_OPERAND_P
- && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand))
-#endif
- )
+ && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand)))
win = 1;
break;
@@ -3261,6 +3309,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
break;
case 'X':
+ force_reload = 0;
win = 1;
break;
@@ -3271,13 +3320,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
&& GET_CODE (operand) != PLUS
/* A SCRATCH is not a valid operand. */
&& GET_CODE (operand) != SCRATCH
-#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! CONSTANT_P (operand)
|| ! flag_pic
|| LEGITIMATE_PIC_OPERAND_P (operand))
-#endif
&& (GENERAL_REGS == ALL_REGS
- || GET_CODE (operand) != REG
+ || !REG_P (operand)
|| (REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0)))
win = 1;
@@ -3300,13 +3347,13 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
win = 1;
/* If the address was already reloaded,
we win as well. */
- else if (GET_CODE (operand) == MEM
- && address_reloaded[i])
+ else if (MEM_P (operand)
+ && address_reloaded[i] == 1)
win = 1;
/* Likewise if the address will be reloaded because
reg_equiv_address is nonzero. For reg_equiv_mem
we have to check. */
- else if (GET_CODE (operand) == REG
+ else if (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
&& ((reg_equiv_mem[REGNO (operand)] != 0
@@ -3317,8 +3364,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* If we didn't already win, we can reload
constants via force_const_mem, and other
MEMs by reloading the address like for 'o'. */
- if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
- || GET_CODE (operand) == MEM)
+ if (CONST_POOL_OK_P (operand)
+ || MEM_P (operand))
badop = 0;
constmemok = 1;
offmemok = 1;
@@ -3331,7 +3378,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* If we didn't already win, we can reload
the address into a base register. */
- this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
+ this_alternative[i]
+ = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
badop = 0;
break;
}
@@ -3350,7 +3398,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
if (GET_MODE (operand) == BLKmode)
break;
winreg = 1;
- if (GET_CODE (operand) == REG
+ if (REG_P (operand)
&& reg_fits_class_p (operand, this_alternative[i],
offset, GET_MODE (recog_data.operand[i])))
win = 1;
@@ -3380,7 +3428,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
if (badop)
bad = 1;
/* Alternative loses if it has no regs for a reg operand. */
- if (GET_CODE (operand) == REG
+ if (REG_P (operand)
&& this_alternative[i] == (int) NO_REGS
&& this_alternative_matches[i] < 0)
bad = 1;
@@ -3393,9 +3441,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
an early reload pass. Note that the test here is
precisely the same as in the code below that calls
force_const_mem. */
- if (CONSTANT_P (operand)
- /* force_const_mem does not accept HIGH. */
- && GET_CODE (operand) != HIGH
+ if (CONST_POOL_OK_P (operand)
&& ((PREFERRED_RELOAD_CLASS (operand,
(enum reg_class) this_alternative[i])
== NO_REGS)
@@ -3407,22 +3453,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
losers++;
}
- /* If we can't reload this value at all, reject this
- alternative. Note that we could also lose due to
- LIMIT_RELOAD_RELOAD_CLASS, but we don't check that
- here. */
-
- if (! CONSTANT_P (operand)
- && (enum reg_class) this_alternative[i] != NO_REGS
- && (PREFERRED_RELOAD_CLASS (operand,
- (enum reg_class) this_alternative[i])
- == NO_REGS))
- bad = 1;
-
/* Alternative loses if it requires a type of reload not
permitted for this insn. We can always reload SCRATCH
and objects with a REG_UNUSED note. */
- else if (GET_CODE (operand) != SCRATCH
+ if (GET_CODE (operand) != SCRATCH
&& modified[i] != RELOAD_READ && no_output_reloads
&& ! find_reg_note (insn, REG_UNUSED, operand))
bad = 1;
@@ -3430,11 +3464,27 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
&& ! const_to_mem)
bad = 1;
-#ifdef DISPARAGE_RELOAD_CLASS
- reject
- += DISPARAGE_RELOAD_CLASS (operand,
- (enum reg_class) this_alternative[i]);
+ /* If we can't reload this value at all, reject this
+ alternative. Note that we could also lose due to
+ LIMIT_RELOAD_CLASS, but we don't check that
+ here. */
+
+ if (! CONSTANT_P (operand)
+ && (enum reg_class) this_alternative[i] != NO_REGS)
+ {
+ if (PREFERRED_RELOAD_CLASS
+ (operand, (enum reg_class) this_alternative[i])
+ == NO_REGS)
+ reject = 600;
+
+#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
+ if (operand_type[i] == RELOAD_FOR_OUTPUT
+ && PREFERRED_OUTPUT_RELOAD_CLASS
+ (operand, (enum reg_class) this_alternative[i])
+ == NO_REGS)
+ reject = 600;
#endif
+ }
/* We prefer to reload pseudos over reloading other things,
since such reloads may be able to be eliminated later.
@@ -3444,7 +3494,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
case where we are forcing a constant into memory and
it will then win since we don't want to have a different
alternative match then. */
- if (! (GET_CODE (operand) == REG
+ if (! (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER)
&& GET_CODE (operand) != SCRATCH
&& ! (const_to_mem && constmemok))
@@ -3481,7 +3531,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
if (! win && ! did_match
&& this_alternative[i] != (int) NO_REGS
&& GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
- && reg_class_size[(int) preferred_class[i]] > 1)
+ && reg_class_size [(int) preferred_class[i]] > 0
+ && ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
{
if (! reg_class_subset_p (this_alternative[i],
preferred_class[i]))
@@ -3511,22 +3562,19 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
early_data = decompose (recog_data.operand[i]);
- if (modified[i] == RELOAD_READ)
- abort ();
+ gcc_assert (modified[i] != RELOAD_READ);
if (this_alternative[i] == NO_REGS)
{
this_alternative_earlyclobber[i] = 0;
- if (this_insn_is_asm)
- error_for_asm (this_insn,
- "`&' constraint used with no register class");
- else
- abort ();
+ gcc_assert (this_insn_is_asm);
+ error_for_asm (this_insn,
+ "%<&%> constraint used with no register class");
}
for (j = 0; j < noperands; j++)
/* Is this an input operand or a memory ref? */
- if ((GET_CODE (recog_data.operand[j]) == MEM
+ if ((MEM_P (recog_data.operand[j])
|| modified[j] != RELOAD_WRITE)
&& j != i
/* Ignore things like match_operator operands. */
@@ -3540,10 +3588,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
&& !immune_p (recog_data.operand[j], recog_data.operand[i],
early_data))
{
- /* If the output is in a single-reg class,
+ /* If the output is in a non-empty few-regs class,
it's costly to reload it, so reload the input instead. */
- if (reg_class_size[this_alternative[i]] == 1
- && (GET_CODE (recog_data.operand[j]) == REG
+ if (SMALL_REGISTER_CLASS_P (this_alternative[i])
+ && (REG_P (recog_data.operand[j])
|| GET_CODE (recog_data.operand[j]) == SUBREG))
{
losers++;
@@ -3660,6 +3708,10 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
pref_or_nothing[commutative + 1] = t;
+ t = address_reloaded[commutative];
+ address_reloaded[commutative] = address_reloaded[commutative + 1];
+ address_reloaded[commutative + 1] = t;
+
memcpy (constraints, recog_data.constraints,
noperands * sizeof (char *));
goto try_swapped;
@@ -3688,7 +3740,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* No alternative works with reloads?? */
if (insn_code_number >= 0)
fatal_insn ("unable to generate reloads for:", insn);
- error_for_asm (insn, "inconsistent operand constraints in an `asm'");
+ error_for_asm (insn, "inconsistent operand constraints in an %<asm%>");
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
n_reloads = 0;
@@ -3775,9 +3827,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
into registers are here changed into memory references. */
for (i = 0; i < noperands; i++)
if (! goal_alternative_win[i]
- && CONSTANT_P (recog_data.operand[i])
- /* force_const_mem does not accept HIGH. */
- && GET_CODE (recog_data.operand[i]) != HIGH
+ && CONST_POOL_OK_P (recog_data.operand[i])
&& ((PREFERRED_RELOAD_CLASS (recog_data.operand[i],
(enum reg_class) goal_alternative[i])
== NO_REGS)
@@ -3794,6 +3844,27 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
goal_alternative_win[i] = 1;
}
+ /* Likewise any invalid constants appearing as operand of a PLUS
+ that is to be reloaded. */
+ for (i = 0; i < noperands; i++)
+ if (! goal_alternative_win[i]
+ && GET_CODE (recog_data.operand[i]) == PLUS
+ && CONST_POOL_OK_P (XEXP (recog_data.operand[i], 1))
+ && (PREFERRED_RELOAD_CLASS (XEXP (recog_data.operand[i], 1),
+ (enum reg_class) goal_alternative[i])
+ == NO_REGS)
+ && operand_mode[i] != VOIDmode)
+ {
+ rtx tem = force_const_mem (operand_mode[i],
+ XEXP (recog_data.operand[i], 1));
+ tem = gen_rtx_PLUS (operand_mode[i],
+ XEXP (recog_data.operand[i], 0), tem);
+
+ substed_operand[i] = recog_data.operand[i]
+ = find_reloads_toplev (tem, i, address_type[i],
+ ind_levels, 0, insn, NULL);
+ }
+
/* Record the values of the earlyclobber operands for the caller. */
if (goal_earlyclobber)
for (i = 0; i < noperands; i++)
@@ -3816,13 +3887,21 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
so we don't bother with it. It may not be worth doing. */
else if (goal_alternative_matched[i] == -1
&& goal_alternative_offmemok[i]
- && GET_CODE (recog_data.operand[i]) == MEM)
+ && MEM_P (recog_data.operand[i]))
{
+ /* If the address to be reloaded is a VOIDmode constant,
+ use Pmode as mode of the reload register, as would have
+ been done by find_reloads_address. */
+ enum machine_mode address_mode;
+ address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
+ if (address_mode == VOIDmode)
+ address_mode = Pmode;
+
operand_reloadnum[i]
= push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
&XEXP (recog_data.operand[i], 0), (rtx*) 0,
- MODE_BASE_REG_CLASS (VOIDmode),
- GET_MODE (XEXP (recog_data.operand[i], 0)),
+ base_reg_class (VOIDmode, MEM, SCRATCH),
+ address_mode,
VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
rld[operand_reloadnum[i]].inc
= GET_MODE_SIZE (GET_MODE (recog_data.operand[i]));
@@ -3898,11 +3977,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
0, 0, i, RELOAD_OTHER);
operand_reloadnum[i] = output_reloadnum;
}
- else if (insn_code_number >= 0)
- abort ();
else
{
- error_for_asm (insn, "inconsistent operand constraints in an `asm'");
+ gcc_assert (insn_code_number < 0);
+ error_for_asm (insn, "inconsistent operand constraints "
+ "in an %<asm%>");
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
n_reloads = 0;
@@ -3911,7 +3990,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
}
else if (goal_alternative_matched[i] < 0
&& goal_alternative_matches[i] < 0
- && !address_operand_reloaded[i]
+ && address_operand_reloaded[i] != 1
&& optimize)
{
/* For each non-matching operand that's a MEM or a pseudo-register
@@ -3922,8 +4001,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
while (GET_CODE (operand) == SUBREG)
operand = SUBREG_REG (operand);
- if ((GET_CODE (operand) == MEM
- || (GET_CODE (operand) == REG
+ if ((MEM_P (operand)
+ || (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
/* If this is only for an output, the optional reload would not
actually cause us to use a register now, just note that
@@ -3963,8 +4042,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
we then need to emit a USE and/or a CLOBBER so that reload
inheritance will do the right thing. */
else if (replace
- && (GET_CODE (operand) == MEM
- || (GET_CODE (operand) == REG
+ && (MEM_P (operand)
+ || (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber [REGNO (operand)] < 0)))
{
@@ -3972,7 +4051,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
while (GET_CODE (operand) == SUBREG)
operand = SUBREG_REG (operand);
- if (GET_CODE (operand) == REG)
+ if (REG_P (operand))
{
if (modified[i] != RELOAD_WRITE)
/* We mark the USE with QImode so that we recognize
@@ -3999,8 +4078,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
while (GET_CODE (operand) == SUBREG)
operand = SUBREG_REG (operand);
- if ((GET_CODE (operand) == MEM
- || (GET_CODE (operand) == REG
+ if ((MEM_P (operand)
+ || (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
&& ((enum reg_class) goal_alternative[goal_alternative_matches[i]]
!= NO_REGS))
@@ -4023,7 +4102,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
{
/* We only do this on the last pass through reload, because it is
possible for some data (like reg_equiv_address) to be changed during
- later passes. Moreover, we loose the opportunity to get a useful
+ later passes. Moreover, we lose the opportunity to get a useful
reload_{in,out}_reg when we do these replacements. */
if (replace)
@@ -4035,7 +4114,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* If we're replacing an operand with a LABEL_REF, we need
to make sure that there's a REG_LABEL note attached to
this instruction. */
- if (GET_CODE (insn) != JUMP_INSN
+ if (!JUMP_P (insn)
&& GET_CODE (substitution) == LABEL_REF
&& !find_reg_note (insn, REG_LABEL, XEXP (substitution, 0)))
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
@@ -4075,7 +4154,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
for (i = 0; i < n_reloads; i++)
if (rld[i].reg_rtx == 0
&& rld[i].in != 0
- && GET_CODE (rld[i].in) == REG
+ && REG_P (rld[i].in)
&& rld[i].out == 0)
{
rld[i].reg_rtx
@@ -4088,6 +4167,12 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
}
#endif
+ /* If we detected error and replaced asm instruction by USE, forget about the
+ reloads. */
+ if (GET_CODE (PATTERN (insn)) == USE
+ && GET_CODE (XEXP (PATTERN (insn), 0)) == CONST_INT)
+ n_reloads = 0;
+
/* Perhaps an output reload can be combined with another
to reduce needs by one. */
if (!goal_earlyclobber)
@@ -4357,10 +4442,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
do after the insn (such as for output addresses) are fine. */
if (no_input_reloads)
for (i = 0; i < n_reloads; i++)
- if (rld[i].in != 0
- && rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS
- && rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS)
- abort ();
+ gcc_assert (rld[i].in == 0
+ || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS
+ || rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS);
#endif
/* Compute reload_mode and reload_nregs. */
@@ -4380,7 +4464,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
for (i = 0; i < n_reloads; i++)
if (rld[i].when_needed == RELOAD_FOR_INPUT
&& GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == REG
+ && REG_P (SET_DEST (PATTERN (insn)))
&& SET_SRC (PATTERN (insn)) == rld[i].in)
{
rtx dest = SET_DEST (PATTERN (insn));
@@ -4390,7 +4474,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
&& TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno)
&& HARD_REGNO_MODE_OK (regno, rld[i].mode))
{
- int nr = HARD_REGNO_NREGS (regno, rld[i].mode);
+ int nr = hard_regno_nregs[regno][rld[i].mode];
int ok = 1, nri;
for (nri = 1; nri < nr; nri ++)
@@ -4491,6 +4575,8 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
x = mem;
i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
opnum, type, ind_levels, insn);
+ if (x != mem)
+ push_reg_equiv_alt_mem (regno, x);
if (address_reloaded)
*address_reloaded = i;
}
@@ -4509,35 +4595,36 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
return tem;
}
- if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG)
+ if (code == SUBREG && REG_P (SUBREG_REG (x)))
{
- /* Check for SUBREG containing a REG that's equivalent to a constant.
- If the constant has a known value, truncate it right now.
- Similarly if we are extracting a single-word of a multi-word
- constant. If the constant is symbolic, allow it to be substituted
- normally. push_reload will strip the subreg later. If the
- constant is VOIDmode, abort because we will lose the mode of
- the register (this should never happen because one of the cases
- above should handle it). */
+ /* Check for SUBREG containing a REG that's equivalent to a
+ constant. If the constant has a known value, truncate it
+ right now. Similarly if we are extracting a single-word of a
+ multi-word constant. If the constant is symbolic, allow it
+ to be substituted normally. push_reload will strip the
+ subreg later. The constant must not be VOIDmode, because we
+ will lose the mode of the register (this should never happen
+ because one of the cases above should handle it). */
int regno = REGNO (SUBREG_REG (x));
rtx tem;
if (subreg_lowpart_p (x)
- && regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
+ && regno >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0
&& (tem = gen_lowpart_common (GET_MODE (x),
reg_equiv_constant[regno])) != 0)
return tem;
- if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
+ if (regno >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0)
{
tem =
simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
- if (!tem)
- abort ();
+ gcc_assert (tem);
return tem;
}
@@ -4554,7 +4641,7 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
a wider mode if we have a paradoxical SUBREG. find_reloads will
force a reload in that case. So we should not do anything here. */
- else if (regno >= FIRST_PSEUDO_REGISTER
+ if (regno >= FIRST_PSEUDO_REGISTER
#ifdef LOAD_EXTEND_OP
&& (GET_MODE_SIZE (GET_MODE (x))
<= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
@@ -4651,8 +4738,9 @@ maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part)
to determine if we may generate output reloads, and where to put USEs
for pseudos that we have to replace with stack slots.
- Value is nonzero if this address is reloaded or replaced as a whole.
- This is interesting to the caller if the address is an autoincrement.
+ Value is one if this address is reloaded or replaced as a whole; it is
+ zero if the top level of this address was not reloaded or replaced, and
+ it is -1 if it may or may not have been reloaded or replaced.
Note that there is no verification that the address will be valid after
this routine does its work. Instead, we rely on the fact that the address
@@ -4667,13 +4755,14 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
{
int regno;
int removed_and = 0;
+ int op_index;
rtx tem;
/* If the address is a register, see if it is a legitimate address and
reload if not. We first handle the cases where we need not reload
or where we must reload in a non-standard way. */
- if (GET_CODE (ad) == REG)
+ if (REG_P (ad))
{
regno = REGNO (ad);
@@ -4696,9 +4785,13 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
tem = make_memloc (ad, regno);
if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
{
+ rtx orig = tem;
+
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum,
ADDR_TYPE (type), ind_levels, insn);
+ if (tem != orig)
+ push_reg_equiv_alt_mem (regno, tem);
}
/* We can avoid a reload if the register's equivalent memory
expression is valid as an indirect memory address.
@@ -4707,9 +4800,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
if (ind_levels > 0
&& strict_memory_address_p (mode, tem)
- && (GET_CODE (XEXP (tem, 0)) == REG
+ && (REG_P (XEXP (tem, 0))
|| (GET_CODE (XEXP (tem, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (tem, 0), 0)) == REG
+ && REG_P (XEXP (XEXP (tem, 0), 0))
&& CONSTANT_P (XEXP (XEXP (tem, 0), 1)))))
{
/* TEM is not the same as what we'll be replacing the
@@ -4740,12 +4833,12 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
subject of a CLOBBER in this insn. */
else if (regno < FIRST_PSEUDO_REGISTER
- && REGNO_MODE_OK_FOR_BASE_P (regno, mode)
+ && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
&& ! regno_clobbered_p (regno, this_insn, mode, 0))
return 0;
/* If we do not have one of the cases above, we must do the reload. */
- push_reload (ad, NULL_RTX, loc, (rtx*) 0, MODE_BASE_REG_CLASS (mode),
+ push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH),
GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -4762,7 +4855,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
/* But first quickly dispose of a common case. */
if (GET_CODE (ad) == PLUS
&& GET_CODE (XEXP (ad, 1)) == CONST_INT
- && GET_CODE (XEXP (ad, 0)) == REG
+ && REG_P (XEXP (ad, 0))
&& reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
return 0;
@@ -4790,7 +4883,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
*memrefloc = copy_rtx (*memrefloc);
XEXP (*memrefloc, 0) = ad;
move_replacements (&ad, &XEXP (*memrefloc, 0));
- return 1;
+ return -1;
}
while (0);
#endif
@@ -4811,7 +4904,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
frame and stack pointers is not its initial value. In that case the
pseudo will have been replaced by a MEM referring to the
stack pointer. */
- if (GET_CODE (ad) == MEM)
+ if (MEM_P (ad))
{
/* First ensure that the address in this MEM is valid. Then, unless
indirect addresses are valid, reload the MEM into a register. */
@@ -4837,16 +4930,16 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
if (ind_levels == 0
|| (GET_CODE (XEXP (tem, 0)) == SYMBOL_REF && ! indirect_symref_ok)
- || GET_CODE (XEXP (tem, 0)) == MEM
- || ! (GET_CODE (XEXP (tem, 0)) == REG
+ || MEM_P (XEXP (tem, 0))
+ || ! (REG_P (XEXP (tem, 0))
|| (GET_CODE (XEXP (tem, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (tem, 0), 0)) == REG
+ && REG_P (XEXP (XEXP (tem, 0), 0))
&& GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)))
{
/* Must use TEM here, not AD, since it is the one that will
have any subexpressions reloaded, if needed. */
push_reload (tem, NULL_RTX, loc, (rtx*) 0,
- MODE_BASE_REG_CLASS (mode), GET_MODE (tem),
+ base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem),
VOIDmode, 0,
0, opnum, type);
return ! removed_and;
@@ -4861,10 +4954,12 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
targets (namely SH) we can also get too large displacements from
big-endian corrections. */
else if (GET_CODE (ad) == PLUS
- && GET_CODE (XEXP (ad, 0)) == REG
+ && REG_P (XEXP (ad, 0))
&& REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
- && REG_MODE_OK_FOR_BASE_P (XEXP (ad, 0), mode)
- && GET_CODE (XEXP (ad, 1)) == CONST_INT)
+ && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
+ CONST_INT))
+
{
/* Unshare the MEM rtx so we can safely alter it. */
if (memrefloc)
@@ -4892,7 +4987,8 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
/* If the sum of two regs is not necessarily valid,
reload the sum into a base reg.
That will at least work. */
- find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
+ find_reloads_address_part (ad, loc,
+ base_reg_class (mode, MEM, SCRATCH),
Pmode, opnum, type, ind_levels);
}
return ! removed_and;
@@ -4912,7 +5008,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
Handle all base registers here, not just fp/ap/sp, because on some
targets (namely SPARC) we can also get invalid addresses from preventive
- subreg big-endian corrections made by find_reloads_toplev.
+ subreg big-endian corrections made by find_reloads_toplev. We
+ can also get expressions involving LO_SUM (rather than PLUS) from
+ find_reloads_subreg_address.
If we decide to do something, it must be that `double_reg_address_ok'
is true. We generate a reload of the base register + constant and
@@ -4920,62 +5018,69 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
This is safe because we know the address isn't shared.
We check for the base register as both the first and second operand of
- the innermost PLUS. */
-
- else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
- && GET_CODE (XEXP (ad, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (ad, 0), 0)) == REG
- && REGNO (XEXP (XEXP (ad, 0), 0)) < FIRST_PSEUDO_REGISTER
- && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 0), mode)
- || XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 0) == arg_pointer_rtx
-#endif
- || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
- && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1)))
+ the innermost PLUS and/or LO_SUM. */
+
+ for (op_index = 0; op_index < 2; ++op_index)
{
- *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
- plus_constant (XEXP (XEXP (ad, 0), 0),
- INTVAL (XEXP (ad, 1))),
- XEXP (XEXP (ad, 0), 1));
- find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (ad), opnum, type, ind_levels);
- find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
- type, 0, insn);
+ rtx operand, addend;
+ enum rtx_code inner_code;
- return 0;
- }
+ if (GET_CODE (ad) != PLUS)
+ continue;
+
+ inner_code = GET_CODE (XEXP (ad, 0));
+ if (!(GET_CODE (ad) == PLUS
+ && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && (inner_code == PLUS || inner_code == LO_SUM)))
+ continue;
- else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
- && GET_CODE (XEXP (ad, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (ad, 0), 1)) == REG
- && REGNO (XEXP (XEXP (ad, 0), 1)) < FIRST_PSEUDO_REGISTER
- && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 1), mode)
- || XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx
+ operand = XEXP (XEXP (ad, 0), op_index);
+ if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
+ continue;
+
+ addend = XEXP (XEXP (ad, 0), 1 - op_index);
+
+ if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code,
+ GET_CODE (addend))
+ || operand == frame_pointer_rtx
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx
+ || operand == hard_frame_pointer_rtx
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx
+ || operand == arg_pointer_rtx
#endif
- || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
- && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0)))
- {
- *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
- XEXP (XEXP (ad, 0), 0),
- plus_constant (XEXP (XEXP (ad, 0), 1),
- INTVAL (XEXP (ad, 1))));
- find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (ad), opnum, type, ind_levels);
- find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
- type, 0, insn);
+ || operand == stack_pointer_rtx)
+ && ! maybe_memory_address_p (mode, ad,
+ &XEXP (XEXP (ad, 0), 1 - op_index)))
+ {
+ rtx offset_reg;
+ enum reg_class cls;
- return 0;
+ offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1)));
+
+ /* Form the adjusted address. */
+ if (GET_CODE (XEXP (ad, 0)) == PLUS)
+ ad = gen_rtx_PLUS (GET_MODE (ad),
+ op_index == 0 ? offset_reg : addend,
+ op_index == 0 ? addend : offset_reg);
+ else
+ ad = gen_rtx_LO_SUM (GET_MODE (ad),
+ op_index == 0 ? offset_reg : addend,
+ op_index == 0 ? addend : offset_reg);
+ *loc = ad;
+
+ cls = base_reg_class (mode, MEM, GET_CODE (addend));
+ find_reloads_address_part (XEXP (ad, op_index),
+ &XEXP (ad, op_index), cls,
+ GET_MODE (ad), opnum, type, ind_levels);
+ find_reloads_address_1 (mode,
+ XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
+ GET_CODE (XEXP (ad, op_index)),
+ &XEXP (ad, 1 - op_index), opnum,
+ type, 0, insn);
+
+ return 0;
+ }
}
/* See if address becomes valid when an eliminable register
@@ -5016,13 +5121,13 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
loc = &XEXP (*loc, 0);
}
- find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
+ find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
Pmode, opnum, type, ind_levels);
return ! removed_and;
}
- return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels,
- insn);
+ return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
+ ind_levels, insn);
}
/* Find all pseudo regs appearing in AD
@@ -5167,12 +5272,12 @@ subst_indexed_address (rtx addr)
{
/* Try to find a register to replace. */
op0 = XEXP (addr, 0), op1 = XEXP (addr, 1), op2 = 0;
- if (GET_CODE (op0) == REG
+ if (REG_P (op0)
&& (regno = REGNO (op0)) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0)
op0 = reg_equiv_constant[regno];
- else if (GET_CODE (op1) == REG
+ else if (REG_P (op1)
&& (regno = REGNO (op1)) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0)
@@ -5234,7 +5339,11 @@ update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
CONTEXT = 1 means we are considering regs as index regs,
= 0 means we are considering them as base regs.
-
+ OUTER_CODE is the code of the enclosing RTX, typically a MEM, a PLUS,
+ or an autoinc code.
+ If CONTEXT == 0 and OUTER_CODE is a PLUS or LO_SUM, then INDEX_CODE
+ is the code of the index part of the address. Otherwise, pass SCRATCH
+ for this argument.
OPNUM and TYPE specify the purpose of any reloads made.
IND_LEVELS says how many levels of indirect addressing are
@@ -5249,15 +5358,29 @@ update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
occurs as part of an address.
Also, this is not fully machine-customizable; it works for machines
such as VAXen and 68000's and 32000's, but other possible machines
- could have addressing modes that this does not handle right. */
+ could have addressing modes that this does not handle right.
+ If you add push_reload calls here, you need to make sure gen_reload
+ handles those cases gracefully. */
static int
find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
+ enum rtx_code outer_code, enum rtx_code index_code,
rtx *loc, int opnum, enum reload_type type,
int ind_levels, rtx insn)
{
+#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX) \
+ ((CONTEXT) == 0 \
+ ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX) \
+ : REGNO_OK_FOR_INDEX_P (REGNO))
+
+ enum reg_class context_reg_class;
RTX_CODE code = GET_CODE (x);
+ if (context == 1)
+ context_reg_class = INDEX_REG_CLASS;
+ else
+ context_reg_class = base_reg_class (mode, outer_code, index_code);
+
switch (code)
{
case PLUS:
@@ -5297,15 +5420,15 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
GET_MODE (orig_op1))));
}
/* Plus in the index register may be created only as a result of
- register remateralization for expression like &localvar*4. Reload it.
+ register rematerialization for expression like &localvar*4. Reload it.
It may be possible to combine the displacement on the outer level,
but it is probably not worthwhile to do so. */
- if (context)
+ if (context == 1)
{
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -5313,74 +5436,90 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
|| code0 == ZERO_EXTEND || code1 == MEM)
{
- find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
}
else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
|| code1 == ZERO_EXTEND || code0 == MEM)
{
- find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
}
else if (code0 == CONST_INT || code0 == CONST
|| code0 == SYMBOL_REF || code0 == LABEL_REF)
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
else if (code1 == CONST_INT || code1 == CONST
|| code1 == SYMBOL_REF || code1 == LABEL_REF)
- find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
else if (code0 == REG && code1 == REG)
{
- if (REG_OK_FOR_INDEX_P (op0)
- && REG_MODE_OK_FOR_BASE_P (op1, mode))
+ if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
+ && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
return 0;
- else if (REG_OK_FOR_INDEX_P (op1)
- && REG_MODE_OK_FOR_BASE_P (op0, mode))
+ else if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
+ && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
return 0;
- else if (REG_MODE_OK_FOR_BASE_P (op1, mode))
- find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- else if (REG_MODE_OK_FOR_BASE_P (op0, mode))
- find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
- else if (REG_OK_FOR_INDEX_P (op1))
- find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- else if (REG_OK_FOR_INDEX_P (op0))
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
+ find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
+ find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
+ else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
else
{
- find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
}
}
else if (code0 == REG)
{
- find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
}
else if (code1 == REG)
{
- find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
}
}
@@ -5391,6 +5530,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
{
rtx op0 = XEXP (x, 0);
rtx op1 = XEXP (x, 1);
+ enum rtx_code index_code;
+ int regno;
+ int reloadnum;
if (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
return 0;
@@ -5399,79 +5541,87 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
where a base register is {inc,dec}remented by the contents
of another register or by a constant value. Thus, these
operands must match. */
- if (op0 != XEXP (op1, 0))
- abort ();
+ gcc_assert (op0 == XEXP (op1, 0));
/* Require index register (or constant). Let's just handle the
register case in the meantime... If the target allows
auto-modify by a constant then we could try replacing a pseudo
- register with its equivalent constant where applicable. */
+ register with its equivalent constant where applicable.
+
+ If we later decide to reload the whole PRE_MODIFY or
+ POST_MODIFY, inc_for_reload might clobber the reload register
+ before reading the index. The index register might therefore
+ need to live longer than a TYPE reload normally would, so be
+ conservative and class it as RELOAD_OTHER. */
if (REG_P (XEXP (op1, 1)))
if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
- find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1),
- opnum, type, ind_levels, insn);
+ find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
+ &XEXP (op1, 1), opnum, RELOAD_OTHER,
+ ind_levels, insn);
- if (REG_P (XEXP (op1, 0)))
- {
- int regno = REGNO (XEXP (op1, 0));
- int reloadnum;
-
- /* A register that is incremented cannot be constant! */
- if (regno >= FIRST_PSEUDO_REGISTER
- && reg_equiv_constant[regno] != 0)
- abort ();
-
- /* Handle a register that is equivalent to a memory location
- which cannot be addressed directly. */
- if (reg_equiv_memory_loc[regno] != 0
- && (reg_equiv_address[regno] != 0
- || num_not_at_initial_offset))
- {
- rtx tem = make_memloc (XEXP (x, 0), regno);
+ gcc_assert (REG_P (XEXP (op1, 0)));
- if (reg_equiv_address[regno]
- || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
- {
- /* First reload the memory location's address.
- We can't use ADDR_TYPE (type) here, because we need to
- write back the value after reading it, hence we actually
- need two registers. */
- find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
- &XEXP (tem, 0), opnum,
- RELOAD_OTHER,
- ind_levels, insn);
-
- /* Then reload the memory location into a base
- register. */
- reloadnum = push_reload (tem, tem, &XEXP (x, 0),
- &XEXP (op1, 0),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (x), GET_MODE (x), 0,
- 0, opnum, RELOAD_OTHER);
-
- update_auto_inc_notes (this_insn, regno, reloadnum);
- return 0;
- }
- }
+ regno = REGNO (XEXP (op1, 0));
+ index_code = GET_CODE (XEXP (op1, 1));
+
+ /* A register that is incremented cannot be constant! */
+ gcc_assert (regno < FIRST_PSEUDO_REGISTER
+ || reg_equiv_constant[regno] == 0);
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
+ /* Handle a register that is equivalent to a memory location
+ which cannot be addressed directly. */
+ if (reg_equiv_memory_loc[regno] != 0
+ && (reg_equiv_address[regno] != 0
+ || num_not_at_initial_offset))
+ {
+ rtx tem = make_memloc (XEXP (x, 0), regno);
- /* We require a base register here... */
- if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+ if (reg_equiv_address[regno]
+ || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
- reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
- &XEXP (op1, 0), &XEXP (x, 0),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (x), GET_MODE (x), 0, 0,
- opnum, RELOAD_OTHER);
+ rtx orig = tem;
+
+ /* First reload the memory location's address.
+ We can't use ADDR_TYPE (type) here, because we need to
+ write back the value after reading it, hence we actually
+ need two registers. */
+ find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
+ &XEXP (tem, 0), opnum,
+ RELOAD_OTHER,
+ ind_levels, insn);
+
+ if (tem != orig)
+ push_reg_equiv_alt_mem (regno, tem);
+
+ /* Then reload the memory location into a base
+ register. */
+ reloadnum = push_reload (tem, tem, &XEXP (x, 0),
+ &XEXP (op1, 0),
+ base_reg_class (mode, code,
+ index_code),
+ GET_MODE (x), GET_MODE (x), 0,
+ 0, opnum, RELOAD_OTHER);
update_auto_inc_notes (this_insn, regno, reloadnum);
return 0;
}
}
- else
- abort ();
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
+ /* We require a base register here... */
+ if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
+ {
+ reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
+ &XEXP (op1, 0), &XEXP (x, 0),
+ base_reg_class (mode, code, index_code),
+ GET_MODE (x), GET_MODE (x), 0, 0,
+ opnum, RELOAD_OTHER);
+
+ update_auto_inc_notes (this_insn, regno, reloadnum);
+ return 0;
+ }
}
return 0;
@@ -5479,16 +5629,15 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
case POST_DEC:
case PRE_INC:
case PRE_DEC:
- if (GET_CODE (XEXP (x, 0)) == REG)
+ if (REG_P (XEXP (x, 0)))
{
int regno = REGNO (XEXP (x, 0));
int value = 0;
rtx x_orig = x;
/* A register that is incremented cannot be constant! */
- if (regno >= FIRST_PSEUDO_REGISTER
- && reg_equiv_constant[regno] != 0)
- abort ();
+ gcc_assert (regno < FIRST_PSEUDO_REGISTER
+ || reg_equiv_constant[regno] == 0);
/* Handle a register that is equivalent to a memory location
which cannot be addressed directly. */
@@ -5499,6 +5648,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
if (reg_equiv_address[regno]
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
+ rtx orig = tem;
+
/* First reload the memory location's address.
We can't use ADDR_TYPE (type) here, because we need to
write back the value after reading it, hence we actually
@@ -5506,6 +5657,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum, type,
ind_levels, insn);
+ if (tem != orig)
+ push_reg_equiv_alt_mem (regno, tem);
/* Put this inside a new increment-expression. */
x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
/* Proceed to reload that, as if it contained a register. */
@@ -5525,9 +5678,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
if (reg_renumber[regno] >= 0)
regno = reg_renumber[regno];
- if ((regno >= FIRST_PSEUDO_REGISTER
- || !(context ? REGNO_OK_FOR_INDEX_P (regno)
- : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
+ if (regno >= FIRST_PSEUDO_REGISTER
+ || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+ index_code))
{
int reloadnum;
@@ -5539,11 +5692,11 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
memory location, since this will make it harder to
reuse address reloads, and increases register pressure.
Also don't do this if we can probably update x directly. */
- rtx equiv = (GET_CODE (XEXP (x, 0)) == MEM
+ rtx equiv = (MEM_P (XEXP (x, 0))
? XEXP (x, 0)
: reg_equiv_mem[regno]);
int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
- if (insn && GET_CODE (insn) == INSN && equiv
+ if (insn && NONJUMP_INSN_P (insn) && equiv
&& memory_operand (equiv, GET_MODE (equiv))
#ifdef HAVE_cc0
&& ! sets_cc0_p (PATTERN (insn))
@@ -5563,8 +5716,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
x = XEXP (x, 0);
reloadnum
= push_reload (x, x, loc, loc,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, RELOAD_OTHER);
}
@@ -5572,8 +5724,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
{
reloadnum
= push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, type);
rld[reloadnum].inc
@@ -5588,7 +5739,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
return value;
}
- else if (GET_CODE (XEXP (x, 0)) == MEM)
+ else if (MEM_P (XEXP (x, 0)))
{
/* This is probably the result of a substitution, by eliminate_regs,
of an equivalent address for a pseudo that was not allocated to a
@@ -5613,8 +5764,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
opnum, type, ind_levels, insn);
reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
rld[reloadnum].inc
= find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
@@ -5627,6 +5777,24 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
}
return 0;
+ case TRUNCATE:
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ /* Look for parts to reload in the inner expression and reload them
+ too, in addition to this operation. Reloading all inner parts in
+ addition to this one shouldn't be necessary, but at this point,
+ we don't know if we can possibly omit any part that *can* be
+ reloaded. Targets that are better off reloading just either part
+ (or perhaps even a different part of an outer expression), should
+ define LEGITIMIZE_RELOAD_ADDRESS. */
+ find_reloads_address_1 (GET_MODE (XEXP (x, 0)), XEXP (x, 0),
+ context, code, SCRATCH, &XEXP (x, 0), opnum,
+ type, ind_levels, insn);
+ push_reload (x, NULL_RTX, loc, (rtx*) 0,
+ context_reg_class,
+ GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ return 1;
+
case MEM:
/* This is probably the result of a substitution, by eliminate_regs, of
an equivalent address for a pseudo that was not allocated to a hard
@@ -5643,7 +5811,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
@@ -5654,8 +5822,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
if (reg_equiv_constant[regno] != 0)
{
find_reloads_address_part (reg_equiv_constant[regno], loc,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), opnum, type, ind_levels);
return 1;
}
@@ -5665,8 +5832,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
if (reg_equiv_mem[regno] != 0)
{
push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -5683,18 +5849,20 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
&XEXP (x, 0), opnum, ADDR_TYPE (type),
ind_levels, insn);
+ if (x != tem)
+ push_reg_equiv_alt_mem (regno, x);
}
}
if (reg_renumber[regno] >= 0)
regno = reg_renumber[regno];
- if ((regno >= FIRST_PSEUDO_REGISTER
- || !(context ? REGNO_OK_FOR_INDEX_P (regno)
- : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
+ if (regno >= FIRST_PSEUDO_REGISTER
+ || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+ index_code))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -5706,7 +5874,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -5714,7 +5882,7 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
return 0;
case SUBREG:
- if (GET_CODE (SUBREG_REG (x)) == REG)
+ if (REG_P (SUBREG_REG (x)))
{
/* If this is a SUBREG of a hard register and the resulting register
is of the wrong class, reload the whole SUBREG. This avoids
@@ -5723,12 +5891,11 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
{
int regno ATTRIBUTE_UNUSED = subreg_regno (x);
- if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
- : REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
+ if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+ index_code))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -5737,12 +5904,12 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
is larger than the class size, then reload the whole SUBREG. */
else
{
- enum reg_class class = (context ? INDEX_REG_CLASS
- : MODE_BASE_REG_CLASS (mode));
+ enum reg_class class = context_reg_class;
if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
> reg_class_size[class])
{
- x = find_reloads_subreg_address (x, 0, opnum, type,
+ x = find_reloads_subreg_address (x, 0, opnum,
+ ADDR_TYPE (type),
ind_levels, insn);
push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
@@ -5763,11 +5930,14 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- find_reloads_address_1 (mode, XEXP (x, i), context, &XEXP (x, i),
- opnum, type, ind_levels, insn);
+ /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
+ we get here. */
+ find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH,
+ &XEXP (x, i), opnum, type, ind_levels, insn);
}
}
+#undef REG_OK_FOR_CONTEXT
return 0;
}
@@ -5868,6 +6038,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
int offset;
+ rtx orig = tem;
+ enum machine_mode orig_mode = GET_MODE (orig);
+ int reloaded;
/* For big-endian paradoxical subregs, SUBREG_BYTE does not
hold the correct (negative) byte offset. */
@@ -5882,7 +6055,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
/* If this was a paradoxical subreg that we replaced, the
resulting memory must be sufficiently aligned to allow
us to widen the mode of the memory. */
- if (outer_size > inner_size && STRICT_ALIGNMENT)
+ if (outer_size > inner_size)
{
rtx base;
@@ -5894,15 +6067,37 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
return x;
base = XEXP (base, 0);
}
- if (GET_CODE (base) != REG
+ if (!REG_P (base)
|| (REGNO_POINTER_ALIGN (REGNO (base))
< outer_size * BITS_PER_UNIT))
return x;
}
- find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, ADDR_TYPE (type),
- ind_levels, insn);
+ reloaded = find_reloads_address (GET_MODE (tem), &tem,
+ XEXP (tem, 0), &XEXP (tem, 0),
+ opnum, type, ind_levels, insn);
+ /* ??? Do we need to handle nonzero offsets somehow? */
+ if (!offset && tem != orig)
+ push_reg_equiv_alt_mem (regno, tem);
+
+ /* For some processors an address may be valid in the
+ original mode but not in a smaller mode. For
+ example, ARM accepts a scaled index register in
+ SImode but not in HImode. find_reloads_address
+ assumes that we pass it a valid address, and doesn't
+ force a reload. This will probably be fine if
+ find_reloads_address finds some reloads. But if it
+ doesn't find any, then we may have just converted a
+ valid address into an invalid one. Check for that
+ here. */
+ if (reloaded != 1
+ && strict_memory_address_p (orig_mode, XEXP (tem, 0))
+ && !strict_memory_address_p (GET_MODE (tem),
+ XEXP (tem, 0)))
+ push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
+ base_reg_class (GET_MODE (tem), MEM, SCRATCH),
+ GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
+ opnum, type);
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so
@@ -5952,10 +6147,9 @@ subst_reloads (rtx insn)
for (check_regno = 0; check_regno < max_regno; check_regno++)
{
#define CHECK_MODF(ARRAY) \
- if (ARRAY[check_regno] \
- && loc_mentioned_in_p (r->where, \
- ARRAY[check_regno])) \
- abort ()
+ gcc_assert (!ARRAY[check_regno] \
+ || !loc_mentioned_in_p (r->where, \
+ ARRAY[check_regno]))
CHECK_MODF (reg_equiv_constant);
CHECK_MODF (reg_equiv_memory_loc);
@@ -5969,10 +6163,13 @@ subst_reloads (rtx insn)
REG_LABEL note to indicate to flow which label this
register refers to. */
if (GET_CODE (*r->where) == LABEL_REF
- && GET_CODE (insn) == JUMP_INSN)
- REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
- XEXP (*r->where, 0),
- REG_NOTES (insn));
+ && JUMP_P (insn))
+ {
+ REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
+ XEXP (*r->where, 0),
+ REG_NOTES (insn));
+ JUMP_LABEL (insn) = XEXP (*r->where, 0);
+ }
/* Encapsulate RELOADREG so its machine mode matches what
used to be there. Note that gen_lowpart_common will
@@ -6010,8 +6207,8 @@ subst_reloads (rtx insn)
*r->where = reloadreg;
}
/* If reload got no reg and isn't optional, something's wrong. */
- else if (! rld[r->what].optional)
- abort ();
+ else
+ gcc_assert (rld[r->what].optional);
}
}
@@ -6023,8 +6220,7 @@ copy_replacements (rtx x, rtx y)
{
/* We can't support X being a SUBREG because we might then need to know its
location if something inside it was replaced. */
- if (GET_CODE (x) == SUBREG)
- abort ();
+ gcc_assert (GET_CODE (x) != SUBREG);
copy_replacements_1 (&x, &y, n_replacements);
}
@@ -6116,7 +6312,7 @@ find_replacement (rtx *loc)
??? Is it actually still ever a SUBREG? If so, why? */
- if (GET_CODE (reloadreg) == REG)
+ if (REG_P (reloadreg))
return gen_rtx_REG (GET_MODE (*loc),
(REGNO (reloadreg) +
subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
@@ -6164,7 +6360,7 @@ find_replacement (rtx *loc)
This is similar to refers_to_regno_p in rtlanal.c except that we
look at equivalences for pseudos that didn't get hard registers. */
-int
+static int
refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
rtx x, rtx *loc)
{
@@ -6193,27 +6389,25 @@ refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
reg_equiv_memory_loc[r],
(rtx*) 0);
- if (reg_equiv_constant[r])
- return 0;
-
- abort ();
+ gcc_assert (reg_equiv_constant[r] || reg_equiv_invariant[r]);
+ return 0;
}
return (endregno > r
&& regno < r + (r < FIRST_PSEUDO_REGISTER
- ? HARD_REGNO_NREGS (r, GET_MODE (x))
+ ? hard_regno_nregs[r][GET_MODE (x)]
: 1));
case SUBREG:
/* If this is a SUBREG of a hard reg, we can see exactly which
registers are being modified. Otherwise, handle normally. */
- if (GET_CODE (SUBREG_REG (x)) == REG
+ if (REG_P (SUBREG_REG (x))
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
unsigned int inner_regno = subreg_regno (x);
unsigned int inner_endregno
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
- ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+ ? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
return endregno > inner_regno && regno < inner_endregno;
}
@@ -6227,14 +6421,14 @@ refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
treat each word individually. */
&& ((GET_CODE (SET_DEST (x)) == SUBREG
&& loc != &SUBREG_REG (SET_DEST (x))
- && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
+ && REG_P (SUBREG_REG (SET_DEST (x)))
&& REGNO (SUBREG_REG (SET_DEST (x))) >= FIRST_PSEUDO_REGISTER
&& refers_to_regno_for_reload_p (regno, endregno,
SUBREG_REG (SET_DEST (x)),
loc))
/* If the output is an earlyclobber operand, this is
a conflict. */
- || ((GET_CODE (SET_DEST (x)) != REG
+ || ((!REG_P (SET_DEST (x))
|| earlyclobber_operand_p (SET_DEST (x)))
&& refers_to_regno_for_reload_p (regno, endregno,
SET_DEST (x), loc))))
@@ -6295,12 +6489,14 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
/* Overly conservative. */
if (GET_CODE (x) == STRICT_LOW_PART
- || GET_RTX_CLASS (GET_CODE (x)) == 'a')
+ || GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
x = XEXP (x, 0);
/* If either argument is a constant, then modifying X can not affect IN. */
if (CONSTANT_P (x) || CONSTANT_P (in))
return 0;
+ else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
+ return refers_to_mem_for_reload_p (in);
else if (GET_CODE (x) == SUBREG)
{
regno = REGNO (SUBREG_REG (x));
@@ -6310,7 +6506,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
SUBREG_BYTE (x),
GET_MODE (x));
}
- else if (GET_CODE (x) == REG)
+ else if (REG_P (x))
{
regno = REGNO (x);
@@ -6321,26 +6517,27 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
{
if (reg_equiv_memory_loc[regno])
return refers_to_mem_for_reload_p (in);
- else if (reg_equiv_constant[regno])
- return 0;
- abort ();
+ gcc_assert (reg_equiv_constant[regno]);
+ return 0;
}
}
- else if (GET_CODE (x) == MEM)
+ else if (MEM_P (x))
return refers_to_mem_for_reload_p (in);
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
|| GET_CODE (x) == CC0)
return reg_mentioned_p (x, in);
- else if (GET_CODE (x) == PLUS)
+ else
{
+ gcc_assert (GET_CODE (x) == PLUS);
+
/* We actually want to know if X is mentioned somewhere inside IN.
We must not say that (plus (sp) (const_int 124)) is in
(plus (sp) (const_int 64)), since that can lead to incorrect reload
allocation when spuriously changing a RELOAD_FOR_OUTPUT_ADDRESS
into a RELOAD_OTHER on behalf of another RELOAD_OTHER. */
- while (GET_CODE (in) == MEM)
+ while (MEM_P (in))
in = XEXP (in, 0);
- if (GET_CODE (in) == REG)
+ if (REG_P (in))
return 0;
else if (GET_CODE (in) == PLUS)
return (reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0))
@@ -6348,11 +6545,9 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
else return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in)
|| reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
}
- else
- abort ();
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
- ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+ ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
}
@@ -6360,23 +6555,23 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
/* Return nonzero if anything in X contains a MEM. Look also for pseudo
registers. */
-int
+static int
refers_to_mem_for_reload_p (rtx x)
{
const char *fmt;
int i;
- if (GET_CODE (x) == MEM)
+ if (MEM_P (x))
return 1;
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
return (REGNO (x) >= FIRST_PSEUDO_REGISTER
&& reg_equiv_memory_loc[REGNO (x)]);
fmt = GET_RTX_FORMAT (GET_CODE (x));
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
if (fmt[i] == 'e'
- && (GET_CODE (XEXP (x, i)) == MEM
+ && (MEM_P (XEXP (x, i))
|| refers_to_mem_for_reload_p (XEXP (x, i))))
return 1;
@@ -6429,14 +6624,14 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
if (goal == 0)
regno = goalreg;
- else if (GET_CODE (goal) == REG)
+ else if (REG_P (goal))
regno = REGNO (goal);
- else if (GET_CODE (goal) == MEM)
+ else if (MEM_P (goal))
{
enum rtx_code code = GET_CODE (XEXP (goal, 0));
if (MEM_VOLATILE_P (goal))
return 0;
- if (flag_float_store && GET_MODE_CLASS (GET_MODE (goal)) == MODE_FLOAT)
+ if (flag_float_store && SCALAR_FLOAT_MODE_P (GET_MODE (goal)))
return 0;
/* An address with side effects must be reexecuted. */
switch (code)
@@ -6475,11 +6670,11 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
{
p = PREV_INSN (p);
num++;
- if (p == 0 || GET_CODE (p) == CODE_LABEL
+ if (p == 0 || LABEL_P (p)
|| num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
return 0;
- if (GET_CODE (p) == INSN
+ if (NONJUMP_INSN_P (p)
/* If we don't want spill regs ... */
&& (! (reload_reg_p != 0
&& reload_reg_p != (short *) (HOST_WIDE_INT) 1)
@@ -6488,7 +6683,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
different from what they were when calculating the need for
spills. If we notice an input-reload insn here, we will
reject it below, but it might hide a usable equivalent.
- That makes bad code. It may even abort: perhaps no reg was
+ That makes bad code. It may even fail: perhaps no reg was
spilled for this insn because it was assumed we would find
that equivalent. */
|| INSN_UID (p) < reload_first_uid))
@@ -6525,10 +6720,9 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
&& ((rtx_equal_p (XEXP (tem, 0), goal)
&& (valueno
= true_regnum (valtry = SET_DEST (pat))) >= 0)
- || (GET_CODE (SET_DEST (pat)) == REG
+ || (REG_P (SET_DEST (pat))
&& GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
- && (GET_MODE_CLASS (GET_MODE (XEXP (tem, 0)))
- == MODE_FLOAT)
+ && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
&& GET_CODE (goal) == CONST_INT
&& 0 != (goaltry
= operand_subword (XEXP (tem, 0), 0, 0,
@@ -6540,10 +6734,9 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
&& (valueno = true_regnum (valtry)) >= 0)))
|| (goal_const && (tem = find_reg_note (p, REG_EQUIV,
NULL_RTX))
- && GET_CODE (SET_DEST (pat)) == REG
+ && REG_P (SET_DEST (pat))
&& GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
- && (GET_MODE_CLASS (GET_MODE (XEXP (tem, 0)))
- == MODE_FLOAT)
+ && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
&& GET_CODE (goal) == CONST_INT
&& 0 != (goaltry = operand_subword (XEXP (tem, 0), 1, 0,
VOIDmode))
@@ -6563,7 +6756,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
{
int i;
- for (i = HARD_REGNO_NREGS (valueno, mode) - 1; i >= 0; i--)
+ for (i = hard_regno_nregs[valueno][mode] - 1; i >= 0; i--)
if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
valueno + i))
break;
@@ -6605,20 +6798,22 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
if (goal_mem && value == SET_DEST (single_set (where))
&& refers_to_regno_for_reload_p (valueno,
(valueno
- + HARD_REGNO_NREGS (valueno, mode)),
+ + hard_regno_nregs[valueno][mode]),
goal, (rtx*) 0))
return 0;
/* Reject registers that overlap GOAL. */
+ if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
+ nregs = hard_regno_nregs[regno][mode];
+ else
+ nregs = 1;
+ valuenregs = hard_regno_nregs[valueno][mode];
+
if (!goal_mem && !goal_const
- && regno + (int) HARD_REGNO_NREGS (regno, mode) > valueno
- && regno < valueno + (int) HARD_REGNO_NREGS (valueno, mode))
+ && regno + nregs > valueno && regno < valueno + valuenregs)
return 0;
- nregs = HARD_REGNO_NREGS (regno, mode);
- valuenregs = HARD_REGNO_NREGS (valueno, mode);
-
/* Reject VALUE if it is one of the regs reserved for reloads.
Reload1 knows how to reuse them anyway, and it would get
confused if we allocated one without its knowledge.
@@ -6643,8 +6838,8 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
if (rld[i].reg_rtx != 0 && rld[i].in)
{
int regno1 = REGNO (rld[i].reg_rtx);
- int nregs1 = HARD_REGNO_NREGS (regno1,
- GET_MODE (rld[i].reg_rtx));
+ int nregs1 = hard_regno_nregs[regno1]
+ [GET_MODE (rld[i].reg_rtx)];
if (regno1 < valueno + valuenregs
&& regno1 + nregs1 > valueno)
return 0;
@@ -6668,7 +6863,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
/* Don't trust the conversion past a function call
if either of the two is in a call-clobbered register, or memory. */
- if (GET_CODE (p) == CALL_INSN)
+ if (CALL_P (p))
{
int i;
@@ -6677,17 +6872,15 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
for (i = 0; i < nregs; ++i)
- if (call_used_regs[regno + i])
+ if (call_used_regs[regno + i]
+ || HARD_REGNO_CALL_PART_CLOBBERED (regno + i, mode))
return 0;
if (valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER)
for (i = 0; i < valuenregs; ++i)
- if (call_used_regs[valueno + i])
+ if (call_used_regs[valueno + i]
+ || HARD_REGNO_CALL_PART_CLOBBERED (valueno + i, mode))
return 0;
-#ifdef NON_SAVING_SETJMP
- if (NON_SAVING_SETJMP && find_reg_note (p, REG_SETJMP, NULL))
- return 0;
-#endif
}
if (INSN_P (p))
@@ -6710,15 +6903,14 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
rtx dest = SET_DEST (pat);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
- if (GET_CODE (dest) == REG)
+ if (REG_P (dest))
{
int xregno = REGNO (dest);
int xnregs;
if (REGNO (dest) < FIRST_PSEUDO_REGISTER)
- xnregs = HARD_REGNO_NREGS (xregno, GET_MODE (dest));
+ xnregs = hard_regno_nregs[xregno][GET_MODE (dest)];
else
xnregs = 1;
if (xregno < regno + nregs && xregno + xnregs > regno)
@@ -6732,10 +6924,10 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
if (xregno == STACK_POINTER_REGNUM && need_stable_sp)
return 0;
}
- else if (goal_mem && GET_CODE (dest) == MEM
+ else if (goal_mem && MEM_P (dest)
&& ! push_operand (dest, GET_MODE (dest)))
return 0;
- else if (GET_CODE (dest) == MEM && regno >= FIRST_PSEUDO_REGISTER
+ else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
&& reg_equiv_memory_loc[regno] != 0)
return 0;
else if (need_stable_sp && push_operand (dest, GET_MODE (dest)))
@@ -6754,15 +6946,14 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
rtx dest = SET_DEST (v1);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
- if (GET_CODE (dest) == REG)
+ if (REG_P (dest))
{
int xregno = REGNO (dest);
int xnregs;
if (REGNO (dest) < FIRST_PSEUDO_REGISTER)
- xnregs = HARD_REGNO_NREGS (xregno, GET_MODE (dest));
+ xnregs = hard_regno_nregs[xregno][GET_MODE (dest)];
else
xnregs = 1;
if (xregno < regno + nregs
@@ -6778,10 +6969,10 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
if (xregno == STACK_POINTER_REGNUM && need_stable_sp)
return 0;
}
- else if (goal_mem && GET_CODE (dest) == MEM
+ else if (goal_mem && MEM_P (dest)
&& ! push_operand (dest, GET_MODE (dest)))
return 0;
- else if (GET_CODE (dest) == MEM && regno >= FIRST_PSEUDO_REGISTER
+ else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
&& reg_equiv_memory_loc[regno] != 0)
return 0;
else if (need_stable_sp
@@ -6791,7 +6982,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
}
}
- if (GET_CODE (p) == CALL_INSN && CALL_INSN_FUNCTION_USAGE (p))
+ if (CALL_P (p) && CALL_INSN_FUNCTION_USAGE (p))
{
rtx link;
@@ -6803,11 +6994,11 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
{
rtx dest = SET_DEST (pat);
- if (GET_CODE (dest) == REG)
+ if (REG_P (dest))
{
int xregno = REGNO (dest);
int xnregs
- = HARD_REGNO_NREGS (xregno, GET_MODE (dest));
+ = hard_regno_nregs[xregno][GET_MODE (dest)];
if (xregno < regno + nregs
&& xregno + xnregs > regno)
@@ -6821,7 +7012,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
return 0;
}
- else if (goal_mem && GET_CODE (dest) == MEM
+ else if (goal_mem && MEM_P (dest)
&& ! push_operand (dest, GET_MODE (dest)))
return 0;
else if (need_stable_sp
@@ -6841,7 +7032,7 @@ find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
for (link = REG_NOTES (p); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_INC
- && GET_CODE (XEXP (link, 0)) == REG)
+ && REG_P (XEXP (link, 0)))
{
int incno = REGNO (XEXP (link, 0));
if (incno < regno + nregs && incno >= regno)
@@ -6915,25 +7106,64 @@ find_inc_amount (rtx x, rtx inced)
return 0;
}
+/* Return 1 if registers from REGNO to ENDREGNO are the subjects of a
+ REG_INC note in insn INSN. REGNO must refer to a hard register. */
+
+#ifdef AUTO_INC_DEC
+static int
+reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
+ rtx insn)
+{
+ rtx link;
+
+ gcc_assert (insn);
+
+ if (! INSN_P (insn))
+ return 0;
+
+ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_INC)
+ {
+ unsigned int test = (int) REGNO (XEXP (link, 0));
+ if (test >= regno && test < endregno)
+ return 1;
+ }
+ return 0;
+}
+#else
+
+#define reg_inc_found_and_valid_p(regno,endregno,insn) 0
+
+#endif
+
/* Return 1 if register REGNO is the subject of a clobber in insn INSN.
- If SETS is nonzero, also consider SETs. */
+ If SETS is 1, also consider SETs. If SETS is 2, enable checking
+ REG_INC. REGNO must refer to a hard register. */
int
regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
int sets)
{
- unsigned int nregs = HARD_REGNO_NREGS (regno, mode);
- unsigned int endregno = regno + nregs;
+ unsigned int nregs, endregno;
+
+ /* regno must be a hard register. */
+ gcc_assert (regno < FIRST_PSEUDO_REGISTER);
+
+ nregs = hard_regno_nregs[regno][mode];
+ endregno = regno + nregs;
if ((GET_CODE (PATTERN (insn)) == CLOBBER
- || (sets && GET_CODE (PATTERN (insn)) == SET))
- && GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
+ || (sets == 1 && GET_CODE (PATTERN (insn)) == SET))
+ && REG_P (XEXP (PATTERN (insn), 0)))
{
unsigned int test = REGNO (XEXP (PATTERN (insn), 0));
return test >= regno && test < endregno;
}
+ if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, insn))
+ return 1;
+
if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
int i = XVECLEN (PATTERN (insn), 0) - 1;
@@ -6942,14 +7172,17 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
{
rtx elt = XVECEXP (PATTERN (insn), 0, i);
if ((GET_CODE (elt) == CLOBBER
- || (sets && GET_CODE (PATTERN (insn)) == SET))
- && GET_CODE (XEXP (elt, 0)) == REG)
+ || (sets == 1 && GET_CODE (PATTERN (insn)) == SET))
+ && REG_P (XEXP (elt, 0)))
{
unsigned int test = REGNO (XEXP (elt, 0));
if (test >= regno && test < endregno)
return 1;
}
+ if (sets == 2
+ && reg_inc_found_and_valid_p (regno, endregno, elt))
+ return 1;
}
}
@@ -6968,8 +7201,8 @@ reload_adjust_reg_for_mode (rtx reloadreg, enum machine_mode mode)
regno = REGNO (reloadreg);
if (WORDS_BIG_ENDIAN)
- regno += HARD_REGNO_NREGS (regno, GET_MODE (reloadreg))
- - HARD_REGNO_NREGS (regno, mode);
+ regno += (int) hard_regno_nregs[regno][GET_MODE (reloadreg)]
+ - (int) hard_regno_nregs[regno][mode];
return gen_rtx_REG (mode, regno);
}
@@ -6989,8 +7222,6 @@ static const char *const reload_when_needed_name[] =
"RELOAD_FOR_OTHER_ADDRESS"
};
-static const char * const reg_class_names[] = REG_CLASS_NAMES;
-
/* These functions are used to print the variables set by 'find_reloads' */
void
diff --git a/contrib/gcc/toplev.c b/contrib/gcc/toplev.c
index da20354..49458c8 100644
--- a/contrib/gcc/toplev.c
+++ b/contrib/gcc/toplev.c
@@ -1,6 +1,7 @@
/* Top level of GCC compilers (cc1, cc1plus, etc.)
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* $FreeBSD$ */
@@ -42,8 +43,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
# include <sys/times.h>
#endif
+#include "line-map.h"
#include "input.h"
#include "tree.h"
+#include "version.h"
#include "rtl.h"
#include "tm_p.h"
#include "flags.h"
@@ -61,7 +64,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "intl.h"
#include "ggc.h"
#include "graph.h"
-#include "loop.h"
#include "regs.h"
#include "timevar.h"
#include "diagnostic.h"
@@ -81,6 +83,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "coverage.h"
#include "value-prof.h"
#include "alloc-pool.h"
+#include "tree-mudflap.h"
#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
#include "dwarf2out.h"
@@ -99,18 +102,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
declarations for e.g. AIX 4.x. */
#endif
-#ifndef HAVE_conditional_execution
-#define HAVE_conditional_execution 0
-#endif
-
-/* Carry information from ASM_DECLARE_OBJECT_NAME
- to ASM_FINISH_DECLARE_OBJECT. */
-
-extern int size_directive_output;
-extern tree last_assemble_variable_decl;
-
-extern void reg_alloc (void);
-
static void general_init (const char *);
static void do_compile (void);
static void process_options (void);
@@ -129,43 +120,6 @@ static int print_single_switch (FILE *, int, int, const char *,
static void print_switch_values (FILE *, int, int, const char *,
const char *, const char *);
-/* Rest of compilation helper functions. */
-static bool rest_of_handle_inlining (tree);
-static void rest_of_handle_cse (tree, rtx);
-static void rest_of_handle_cse2 (tree, rtx);
-static void rest_of_handle_gcse (tree, rtx);
-static void rest_of_handle_life (tree, rtx);
-static void rest_of_handle_loop_optimize (tree, rtx);
-static void rest_of_handle_loop2 (tree, rtx);
-static void rest_of_handle_jump_bypass (tree, rtx);
-static void rest_of_handle_sibling_calls (rtx);
-static void rest_of_handle_null_pointer (tree, rtx);
-static void rest_of_handle_addressof (tree, rtx);
-static void rest_of_handle_cfg (tree, rtx);
-static void rest_of_handle_branch_prob (tree, rtx);
-static void rest_of_handle_value_profile_transformations (tree, rtx);
-static void rest_of_handle_if_conversion (tree, rtx);
-static void rest_of_handle_if_after_combine (tree, rtx);
-static void rest_of_handle_tracer (tree, rtx);
-static void rest_of_handle_combine (tree, rtx);
-static void rest_of_handle_regmove (tree, rtx);
-#ifdef INSN_SCHEDULING
-static void rest_of_handle_sched (tree, rtx);
-static void rest_of_handle_sched2 (tree, rtx);
-#endif
-static bool rest_of_handle_new_regalloc (tree, rtx);
-static bool rest_of_handle_old_regalloc (tree, rtx);
-static void rest_of_handle_regrename (tree, rtx);
-static void rest_of_handle_reorder_blocks (tree, rtx);
-#ifdef STACK_REGS
-static void rest_of_handle_stack_regs (tree, rtx);
-#endif
-static void rest_of_handle_machine_reorg (tree, rtx);
-#ifdef DELAY_SLOTS
-static void rest_of_handle_delay_slots (tree, rtx);
-#endif
-static void rest_of_handle_final (tree, rtx);
-
/* Nonzero to dump debug info whilst parsing (-dy option). */
static int set_yydebug;
@@ -188,10 +142,20 @@ static const char **save_argv;
const char *main_input_filename;
+#ifndef USE_MAPPED_LOCATION
+location_t unknown_location = { NULL, 0 };
+#endif
+
+/* Used to enable -fvar-tracking, -fweb and -frename-registers according
+ to optimize and default_debug_hooks in process_options (). */
+#define AUTODETECT_VALUE 2
+
/* Current position in real source file. */
location_t input_location;
+struct line_maps line_table;
+
/* Nonzero if it is unsafe to create any new pseudo registers. */
int no_new_pseudos;
@@ -202,6 +166,16 @@ struct file_stack *input_file_stack;
/* Incremented on each change to input_file_stack. */
int input_file_stack_tick;
+/* Record of input_file_stack at each tick. */
+typedef struct file_stack *fs_p;
+DEF_VEC_P(fs_p);
+DEF_VEC_ALLOC_P(fs_p,heap);
+static VEC(fs_p,heap) *input_file_stack_history;
+
+/* Whether input_file_stack has been restored to a previous state (in
+ which case there should be no more pushing). */
+static bool input_file_stack_restored;
+
/* Name to use as base of names for dump output files. */
const char *dump_base_name;
@@ -210,11 +184,6 @@ const char *dump_base_name;
const char *aux_base_name;
-/* Format to use to print dumpfile index value */
-#ifndef DUMPFILE_FORMAT
-#define DUMPFILE_FORMAT ".%02d."
-#endif
-
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
and set by `-m...' switches. Must be defined in rtlanal.c. */
@@ -230,123 +199,9 @@ int target_flags_explicit;
const struct gcc_debug_hooks *debug_hooks;
-/* Describes a dump file. */
+/* Debug hooks - target default. */
-struct dump_file_info
-{
- /* The unique extension to apply, e.g. ".jump". */
- const char *const extension;
-
- /* The -d<c> character that enables this dump file. */
- char const debug_switch;
-
- /* True if there is a corresponding graph dump file. */
- char const graph_dump_p;
-
- /* True if the user selected this dump. */
- char enabled;
-
- /* True if the files have been initialized (ie truncated). */
- char initialized;
-};
-
-/* Enumerate the extant dump files. */
-
-enum dump_file_index
-{
- DFI_cgraph,
- DFI_rtl,
- DFI_sibling,
- DFI_eh,
- DFI_jump,
- DFI_null,
- DFI_cse,
- DFI_addressof,
- DFI_gcse,
- DFI_loop,
- DFI_bypass,
- DFI_cfg,
- DFI_bp,
- DFI_vpt,
- DFI_ce1,
- DFI_tracer,
- DFI_loop2,
- DFI_web,
- DFI_cse2,
- DFI_life,
- DFI_combine,
- DFI_ce2,
- DFI_regmove,
- DFI_sched,
- DFI_lreg,
- DFI_greg,
- DFI_postreload,
- DFI_flow2,
- DFI_peephole2,
- DFI_ce3,
- DFI_rnreg,
- DFI_bbro,
- DFI_branch_target_load,
- DFI_sched2,
- DFI_stack,
- DFI_mach,
- DFI_dbr,
- DFI_MAX
-};
-
-/* Describes all the dump files. Should be kept in order of the
- pass and in sync with dump_file_index above.
-
- Remaining -d letters:
-
- " e m q "
- " JK O Q WXY "
-*/
-
-static struct dump_file_info dump_file[DFI_MAX] =
-{
- { "cgraph", 'U', 0, 0, 0 },
- { "rtl", 'r', 0, 0, 0 },
- { "sibling", 'i', 0, 0, 0 },
- { "eh", 'h', 0, 0, 0 },
- { "jump", 'j', 0, 0, 0 },
- { "null", 'u', 0, 0, 0 },
- { "cse", 's', 0, 0, 0 },
- { "addressof", 'F', 0, 0, 0 },
- { "gcse", 'G', 1, 0, 0 },
- { "loop", 'L', 1, 0, 0 },
- { "bypass", 'G', 1, 0, 0 }, /* Yes, duplicate enable switch. */
- { "cfg", 'f', 1, 0, 0 },
- { "bp", 'b', 1, 0, 0 },
- { "vpt", 'V', 1, 0, 0 },
- { "ce1", 'C', 1, 0, 0 },
- { "tracer", 'T', 1, 0, 0 },
- { "loop2", 'L', 1, 0, 0 },
- { "web", 'Z', 0, 0, 0 },
- { "cse2", 't', 1, 0, 0 },
- { "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */
- { "combine", 'c', 1, 0, 0 },
- { "ce2", 'C', 1, 0, 0 },
- { "regmove", 'N', 1, 0, 0 },
- { "sched", 'S', 1, 0, 0 },
- { "lreg", 'l', 1, 0, 0 },
- { "greg", 'g', 1, 0, 0 },
- { "postreload", 'o', 1, 0, 0 },
- { "flow2", 'w', 1, 0, 0 },
- { "peephole2", 'z', 1, 0, 0 },
- { "ce3", 'E', 1, 0, 0 },
- { "rnreg", 'n', 1, 0, 0 },
- { "bbro", 'B', 1, 0, 0 },
- { "btl", 'd', 1, 0, 0 }, /* Yes, duplicate enable switch. */
- { "sched2", 'R', 1, 0, 0 },
- { "stack", 'k', 1, 0, 0 },
- { "mach", 'M', 1, 0, 0 },
- { "dbr", 'd', 0, 0, 0 },
-};
-
-static int open_dump_file (enum dump_file_index, tree);
-static void close_dump_file (enum dump_file_index,
- void (*) (FILE *, rtx), rtx);
+static const struct gcc_debug_hooks *default_debug_hooks;
/* Other flags saying which kinds of debugging dump have been requested. */
@@ -378,80 +233,15 @@ int optimize_size = 0;
or 0 if between functions. */
tree current_function_decl;
-/* Set to the FUNC_BEGIN label of the current function, or NULL_TREE
+/* Set to the FUNC_BEGIN label of the current function, or NULL
if none. */
-tree current_function_func_begin_label;
-
-/* Nonzero if doing dwarf2 duplicate elimination. */
-
-int flag_eliminate_dwarf2_dups = 0;
-
-/* Nonzero if doing unused type elimination. */
-
-int flag_eliminate_unused_debug_types = 1;
-
-/* Nonzero means emit debugging information only for symbols which are used. */
-int flag_debug_only_used_symbols = 0;
-
-/* Nonzero if generating code to do profiling. */
-
-int profile_flag = 0;
-
-/* Nonzero if generating code to profile program flow graph arcs. */
-
-int profile_arc_flag = 0;
-
-/* Nonzero if value histograms should be measured. */
-
-int flag_profile_values = 0;
-
-/* Nonzero if value histograms should be used to optimize code. */
-int flag_value_profile_transformations = 0;
-
-/* Nonzero if generating info for gcov to calculate line test coverage. */
-
-int flag_test_coverage = 0;
-
-/* Nonzero indicates that branch taken probabilities should be calculated. */
-
-int flag_branch_probabilities = 0;
-
-/* Nonzero if basic blocks should be reordered. */
-
-int flag_reorder_blocks = 0;
-
-/* Nonzero if functions should be reordered. */
-
-int flag_reorder_functions = 0;
-
-/* Nonzero if registers should be renamed. */
-
-int flag_rename_registers = 0;
-int flag_cprop_registers = 0;
-
-/* Nonzero for -pedantic switch: warn about anything
- that standard spec forbids. */
-
-int pedantic = 0;
+const char * current_function_func_begin_label;
/* Temporarily suppress certain warnings.
This is set while reading code from a system header file. */
int in_system_header = 0;
-/* Don't print functions as they are compiled. -quiet. */
-
-int quiet_flag = 0;
-
-/* Print times taken by the various passes. -ftime-report. */
-
-int time_report = 0;
-
-/* Print memory still in use at end of compilation (which may have little
- to do with peak memory consumption). -fmem-report. */
-
-int mem_report = 0;
-
/* Nonzero means to collect statistics which might be expensive
and to print them when we are done. */
int flag_detailed_statistics = 0;
@@ -470,16 +260,11 @@ unsigned local_tick;
int flag_signed_char;
-/* Nonzero means give an enum type only as many bytes as it needs. */
+/* Nonzero means give an enum type only as many bytes as it needs. A value
+ of 2 means it has not yet been initialized. */
int flag_short_enums;
-/* Nonzero for -fcaller-saves: allocate values in regs that need to
- be saved across function calls, if that produces overall better code.
- Optional now, so people can test it. */
-
-int flag_caller_saves = 0;
-
/* Nonzero if structures and unions should be returned in memory.
This should only be defined if compatibility with another compiler or
@@ -493,259 +278,17 @@ int flag_caller_saves = 0;
int flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
-/* Nonzero for -fforce-mem: load memory value into a register
- before arithmetic on it. This makes better cse but slower compilation. */
-
-int flag_force_mem = 0;
-
-/* Nonzero for -fforce-addr: load memory address into a register before
- reference to memory. This makes better cse but slower compilation. */
-
-int flag_force_addr = 0;
-
-/* Nonzero for -fdefer-pop: don't pop args after each function call;
- instead save them up to pop many calls' args with one insns. */
-
-int flag_defer_pop = 0;
-
-/* Nonzero for -ffloat-store: don't allocate floats and doubles
- in extended-precision registers. */
-
-int flag_float_store = 0;
-
-/* Nonzero for -fcse-follow-jumps:
- have cse follow jumps to do a more extensive job. */
-
-int flag_cse_follow_jumps;
-
-/* Nonzero for -fcse-skip-blocks:
- have cse follow a branch around a block. */
-int flag_cse_skip_blocks;
-
-/* Nonzero for -fexpensive-optimizations:
- perform miscellaneous relatively-expensive optimizations. */
-int flag_expensive_optimizations;
-
-/* Nonzero for -fthread-jumps:
- have jump optimize output of loop. */
-
-int flag_thread_jumps;
-
-/* Nonzero enables strength-reduction in loop.c. */
-
-int flag_strength_reduce = 0;
-
-/* Nonzero enables loop unrolling in unroll.c. Only loops for which the
- number of iterations can be calculated at compile-time (UNROLL_COMPLETELY,
- UNROLL_MODULO) or at run-time (preconditioned to be UNROLL_MODULO) are
- unrolled. */
-
-int flag_old_unroll_loops;
-
-/* Nonzero enables loop unrolling in unroll.c. All loops are unrolled.
- This is generally not a win. */
-
-int flag_old_unroll_all_loops;
-
-/* Enables unrolling of simple loops in loop-unroll.c. */
-int flag_unroll_loops;
-
-/* Enables unrolling of all loops in loop-unroll.c. */
-int flag_unroll_all_loops;
-
-/* Nonzero enables loop peeling. */
-int flag_peel_loops;
-
-/* Nonzero enables loop unswitching. */
-int flag_unswitch_loops;
-
-/* Nonzero enables prefetch optimizations for arrays in loops. */
-
-int flag_prefetch_loop_arrays;
-
-/* Nonzero forces all invariant computations in loops to be moved
- outside the loop. */
-
-int flag_move_all_movables = 0;
-
-/* Nonzero forces all general induction variables in loops to be
- strength reduced. */
-
-int flag_reduce_all_givs = 0;
-
-/* Nonzero to perform full register move optimization passes. This is the
- default for -O2. */
-
-int flag_regmove = 0;
-
-/* Nonzero for -fwritable-strings:
- store string constants in data segment and don't uniquize them. */
-
-int flag_writable_strings = 0;
-
-/* Nonzero means don't put addresses of constant functions in registers.
- Used for compiling the Unix kernel, where strange substitutions are
- done on the assembly output. */
-
-int flag_no_function_cse = 0;
-
-/* Nonzero for -fomit-frame-pointer:
- don't make a frame pointer in simple functions that don't require one. */
-
-int flag_omit_frame_pointer = 0;
-
-/* Nonzero means place each function into its own section on those platforms
- which support arbitrary section names and unlimited numbers of sections. */
-
-int flag_function_sections = 0;
-
-/* ... and similar for data. */
-
-int flag_data_sections = 0;
-
-/* Nonzero to inhibit use of define_optimization peephole opts. */
-
-int flag_no_peephole = 0;
-
-/* Nonzero allows GCC to optimize sibling and tail recursive calls. */
-
-int flag_optimize_sibling_calls = 0;
-
-/* Nonzero means the front end generally wants `errno' maintained by math
- operations, like built-in SQRT. */
-
-int flag_errno_math = 1;
-
-/* Nonzero means that unsafe floating-point math optimizations are allowed
- for the sake of speed. IEEE compliance is not guaranteed, and operations
- are allowed to assume that their arguments and results are "normal"
- (e.g., nonnegative for SQRT). */
-
-int flag_unsafe_math_optimizations = 0;
-
-/* Nonzero means that no NaNs or +-Infs are expected. */
-
-int flag_finite_math_only = 0;
-
-/* Zero means that floating-point math operations cannot generate a
- (user-visible) trap. This is the case, for example, in nonstop
- IEEE 754 arithmetic. Trapping conditions include division by zero,
- overflow, underflow, invalid and inexact, but does not include
- operations on signaling NaNs (see below). */
-
-int flag_trapping_math = 1;
-
-/* Nonzero means disable transformations that assume default floating
- point rounding behavior. */
-
-int flag_rounding_math = 0;
-
-/* Nonzero means disable transformations observable by signaling NaNs.
- This option implies that any operation on an IEEE signaling NaN can
- generate a (user-visible) trap. */
-
-int flag_signaling_nans = 0;
-
/* 0 means straightforward implementation of complex divide acceptable.
1 means wide ranges of inputs must work for complex divide.
- 2 means C99-like requirements for complex divide (not yet implemented). */
-
-int flag_complex_divide_method = 0;
-
-/* Nonzero means just do syntax checking; don't output anything. */
-
-int flag_syntax_only = 0;
-
-/* Nonzero means performs web construction pass. */
-
-int flag_web;
-
-/* Nonzero means perform loop optimizer. */
-
-int flag_loop_optimize;
-
-/* Nonzero means perform crossjumping. */
-
-int flag_crossjumping;
-
-/* Nonzero means perform if conversion. */
-
-int flag_if_conversion;
-
-/* Nonzero means perform if conversion after reload. */
-
-int flag_if_conversion2;
-
-/* Nonzero means to use global dataflow analysis to eliminate
- useless null pointer tests. */
-
-int flag_delete_null_pointer_checks;
-
-/* Nonzero means perform global CSE. */
+ 2 means C99-like requirements for complex multiply and divide. */
-int flag_gcse = 0;
-
-/* Nonzero means to do the enhanced load motion during gcse, which trys
- to hoist loads by not killing them when a store to the same location
- is seen. */
-
-int flag_gcse_lm = 1;
-
-/* Nonzero means to perform store motion after gcse, which will try to
- move stores closer to the exit block. Its not very effective without
- flag_gcse_lm. */
-
-int flag_gcse_sm = 1;
-
-/* Nonzero if we want to perfrom redundant load after store elimination
- in gcse. */
-
-int flag_gcse_las = 1;
-
-/* Perform target register optimization before prologue / epilogue
- threading. */
-
-int flag_branch_target_load_optimize = 0;
-
-/* Perform target register optimization after prologue / epilogue
- threading and jump2. */
-
-int flag_branch_target_load_optimize2 = 0;
-
-/* Nonzero means to rerun cse after loop optimization. This increases
- compilation time about 20% and picks up a few more common expressions. */
-
-int flag_rerun_cse_after_loop;
-
-/* Nonzero means to run loop optimizations twice. */
-
-int flag_rerun_loop_opt;
-
-/* Nonzero for -finline-functions: ok to inline functions that look like
- good inline candidates. */
-
-int flag_inline_functions;
-
-/* Nonzero for -fkeep-inline-functions: even if we make a function
- go inline everywhere, keep its definition around for debugging
- purposes. */
-
-int flag_keep_inline_functions;
-
-/* Nonzero means that functions will not be inlined. */
-
-int flag_no_inline = 2;
+int flag_complex_method = 1;
/* Nonzero means that we don't want inlining by virtue of -fno-inline,
not just because the tree inliner turned us off. */
int flag_really_no_inline = 2;
-/* Nonzero means that we should emit static const variables
- regardless of whether or not optimization is turned on. */
-
-int flag_keep_static_consts = 1;
-
/* Nonzero means we should be saving declaration info into a .X file. */
int flag_gen_aux_info = 0;
@@ -754,124 +297,28 @@ int flag_gen_aux_info = 0;
const char *aux_info_file_name;
-/* Nonzero means make the text shared if supported. */
-
-int flag_shared_data;
-
-/* Nonzero means schedule into delayed branch slots if supported. */
-
-int flag_delayed_branch;
-
-/* Nonzero if we are compiling pure (sharable) code.
- Value is 1 if we are doing "small" pic; value is 2 if we're doing
- "large" pic. */
-
-int flag_pic;
-
-/* Nonzero if we are compiling position independent code for executable.
- The value is 1 if we are doing "small" pic; value is 2 if we're doing
- "large" pic. */
-
-int flag_pie;
-
/* Nonzero if we are compiling code for a shared library, zero for
executable. */
int flag_shlib;
-/* Set to the default thread-local storage (tls) model to use. */
-
-enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
-
-/* Nonzero means generate extra code for exception handling and enable
- exception handling. */
-
-int flag_exceptions;
+/* Generate code for GNU or NeXT Objective-C runtime environment. */
-/* Nonzero means generate frame unwind info table when supported. */
-
-int flag_unwind_tables = 0;
-
-/* Nonzero means generate frame unwind info table exact at each insn
- boundary. */
-
-int flag_asynchronous_unwind_tables = 0;
+#ifdef NEXT_OBJC_RUNTIME
+int flag_next_runtime = 1;
+#else
+int flag_next_runtime = 0;
+#endif
-/* Nonzero means don't place uninitialized global data in common storage
- by default. */
+/* Set to the default thread-local storage (tls) model to use. */
-int flag_no_common;
+enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
/* Nonzero means change certain warnings into errors.
Usually these are warnings about failure to conform to some standard. */
int flag_pedantic_errors = 0;
-/* flag_schedule_insns means schedule insns within basic blocks (before
- local_alloc).
- flag_schedule_insns_after_reload means schedule insns after
- global_alloc. */
-
-int flag_schedule_insns = 0;
-int flag_schedule_insns_after_reload = 0;
-
-/* When flag_schedule_insns_after_reload is set, use EBB scheduler. */
-int flag_sched2_use_superblocks = 0;
-
-/* When flag_schedule_insns_after_reload is set, construct traces and EBB
- scheduler. */
-int flag_sched2_use_traces = 0;
-
-/* The following flags have effect only for scheduling before register
- allocation:
-
- flag_schedule_interblock means schedule insns across basic blocks.
- flag_schedule_speculative means allow speculative motion of non-load insns.
- flag_schedule_speculative_load means allow speculative motion of some
- load insns.
- flag_schedule_speculative_load_dangerous allows speculative motion of more
- load insns. */
-
-int flag_schedule_interblock = 1;
-int flag_schedule_speculative = 1;
-int flag_schedule_speculative_load = 0;
-int flag_schedule_speculative_load_dangerous = 0;
-
-/* The following flags have an effect during scheduling after register
- allocation:
-
- flag_sched_stalled_insns means that insns can be moved prematurely from the queue
- of stalled insns into the ready list.
-
- flag_sched_stalled_insns_dep controls how many insn groups will be examined
- for a dependency on a stalled insn that is candidate for premature removal
- from the queue of stalled insns into the ready list (has an effect only if
- the flag 'sched_stalled_insns' is set). */
-
-int flag_sched_stalled_insns = 0;
-int flag_sched_stalled_insns_dep = 1;
-
-int flag_single_precision_constant;
-
-/* flag_branch_on_count_reg means try to replace add-1,compare,branch tupple
- by a cheaper branch on a count register. */
-int flag_branch_on_count_reg = 1;
-
-/* -finhibit-size-directive inhibits output of .size for ELF.
- This is used only for compiling crtstuff.c,
- and it may be extended to other effects
- needed for crtstuff.c on other systems. */
-int flag_inhibit_size_directive = 0;
-
-/* -fverbose-asm causes extra commentary information to be produced in
- the generated assembly code (to make it more readable). This option
- is generally only of use to those who actually need to read the
- generated assembly code (perhaps while debugging the compiler itself).
- -fno-verbose-asm, the default, causes the extra information
- to be omitted and is useful when comparing two assembler files. */
-
-int flag_verbose_asm = 0;
-
/* -dA causes debug commentary information to be produced in
the generated assembly code (to make it more readable). This option
is generally only of use to those who actually need to read the
@@ -885,19 +332,6 @@ int flag_debug_asm = 0;
int flag_dump_rtl_in_asm = 0;
-/* Nonzero means put zero initialized data in the bss section. */
-int flag_zero_initialized_in_bss = 1;
-
-/* Tag all structures with __attribute__(packed). */
-int flag_pack_struct = 0;
-
-/* Nonzero means that -Wformat accepts certain system-dependent formats. */
-int flag_format_extensions = 0;
-
-/* Emit code to check for stack overflow; also may cause large objects
- to be allocated dynamically. */
-int flag_stack_check;
-
/* When non-NULL, indicates that whenever space is allocated on the
stack, the resulting stack pointer must not pass this
address---that is, for stacks that grow downward, the stack pointer
@@ -907,77 +341,32 @@ int flag_stack_check;
the support provided depends on the backend. */
rtx stack_limit_rtx;
-/* 0 if pointer arguments may alias each other. True in C.
- 1 if pointer arguments may not alias each other but may alias
- global variables.
- 2 if pointer arguments may not alias each other and may not
- alias global variables. True in Fortran.
- This defaults to 0 for C. */
-int flag_argument_noalias = 0;
-
-/* Nonzero if we should do (language-dependent) alias analysis.
- Typically, this analysis will assume that expressions of certain
- types do not alias expressions of certain other types. Only used
- if alias analysis (in general) is enabled. */
-int flag_strict_aliasing = 0;
-
-/* Instrument functions with calls at entry and exit, for profiling. */
-int flag_instrument_function_entry_exit = 0;
-
-/* Nonzero means ignore `#ident' directives. 0 means handle them.
- On SVR4 targets, it also controls whether or not to emit a
- string identifying the compiler. */
-
-int flag_no_ident = 0;
-
-/* This will perform a peephole pass before sched2. */
-int flag_peephole2 = 0;
-
-/* This will try to guess branch probabilities. */
-int flag_guess_branch_prob = 0;
-
-/* -fcheck-bounds causes gcc to generate array bounds checks.
- For C, C++, ObjC: defaults to off.
- For Java: defaults to on.
- For Fortran: defaults to off. */
-int flag_bounds_check = 0;
-
-/* This will attempt to merge constant section constants, if 1 only
- string constants and constants from constant pool, if 2 also constant
- variables. */
-int flag_merge_constants = 1;
-
/* If one, renumber instruction UIDs to reduce the number of
unused UIDs if there are a lot of instructions. If greater than
one, unconditionally renumber instruction UIDs. */
int flag_renumber_insns = 1;
-/* If nonzero, use the graph coloring register allocator. */
-int flag_new_regalloc = 0;
-
-/* Nonzero if we perform superblock formation. */
+/* Nonzero if we should track variables. When
+ flag_var_tracking == AUTODETECT_VALUE it will be set according
+ to optimize, debug_info_level and debug_hooks in process_options (). */
+int flag_var_tracking = AUTODETECT_VALUE;
-int flag_tracer = 0;
+/* True if the user has tagged the function with the 'section'
+ attribute. */
-/* Nonzero if we perform whole unit at a time compilation. */
-
-int flag_unit_at_a_time = 0;
+bool user_defined_section_attribute = false;
/* Values of the -falign-* flags: how much to align labels in code.
0 means `use default', 1 means `don't align'.
For each variable, there is an _log variant which is the power
of two not less than the variable, for .align output. */
-int align_loops;
int align_loops_log;
int align_loops_max_skip;
-int align_jumps;
int align_jumps_log;
int align_jumps_max_skip;
-int align_labels;
int align_labels_log;
int align_labels_max_skip;
-int align_functions;
int align_functions_log;
/* Like align_functions_log above, but used by front-ends to force the
@@ -992,216 +381,27 @@ typedef struct
}
lang_independent_options;
-/* Nonzero if signed arithmetic overflow should trap. */
-int flag_trapv = 0;
-
-/* Nonzero if signed arithmetic overflow should wrap around. */
-int flag_wrapv = 0;
-
/* Nonzero if subexpressions must be evaluated from left-to-right. */
int flag_evaluation_order = 0;
-/* Add or remove a leading underscore from user symbols. */
-int flag_leading_underscore = -1;
-
-/* The version of the C++ ABI in use. The following values are
- allowed:
-
- 0: The version of the ABI believed most conformant with the
- C++ ABI specification. This ABI may change as bugs are
- discovered and fixed. Therefore, 0 will not necessarily
- indicate the same ABI in different versions of G++.
-
- 1: The version of the ABI first used in G++ 3.2.
-
- 2: The version of the ABI first used in G++ 3.4.
-
- Additional positive integers will be assigned as new versions of
- the ABI become the default version of the ABI. */
-
-int flag_abi_version = 2;
-
/* The user symbol prefix after having resolved same. */
const char *user_label_prefix;
static const param_info lang_independent_params[] = {
-#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT) \
- { OPTION, DEFAULT, HELP },
+#define DEFPARAM(ENUM, OPTION, HELP, DEFAULT, MIN, MAX) \
+ { OPTION, DEFAULT, MIN, MAX, HELP },
#include "params.def"
#undef DEFPARAM
- { NULL, 0, NULL }
+ { NULL, 0, 0, 0, NULL }
};
-/* Table of language-independent -f options.
- STRING is the option name. VARIABLE is the address of the variable.
- ON_VALUE is the value to store in VARIABLE
- if `-fSTRING' is seen as an option.
- (If `-fno-STRING' is seen as an option, the opposite value is stored.) */
-
-static const lang_independent_options f_options[] =
-{
- {"format-extensions", &flag_format_extensions, 1},
- {"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1 },
- {"eliminate-unused-debug-symbols", &flag_debug_only_used_symbols, 1 },
- {"eliminate-unused-debug-types", &flag_eliminate_unused_debug_types, 1 },
- {"float-store", &flag_float_store, 1 },
- {"defer-pop", &flag_defer_pop, 1 },
- {"omit-frame-pointer", &flag_omit_frame_pointer, 1 },
- {"optimize-sibling-calls", &flag_optimize_sibling_calls, 1 },
- {"tracer", &flag_tracer, 1 },
- {"unit-at-a-time", &flag_unit_at_a_time, 1 },
- {"cse-follow-jumps", &flag_cse_follow_jumps, 1 },
- {"cse-skip-blocks", &flag_cse_skip_blocks, 1 },
- {"expensive-optimizations", &flag_expensive_optimizations, 1 },
- {"thread-jumps", &flag_thread_jumps, 1 },
- {"strength-reduce", &flag_strength_reduce, 1 },
- {"unroll-loops", &flag_unroll_loops, 1 },
- {"unroll-all-loops", &flag_unroll_all_loops, 1 },
- {"old-unroll-loops", &flag_old_unroll_loops, 1 },
- {"old-unroll-all-loops", &flag_old_unroll_all_loops, 1 },
- {"peel-loops", &flag_peel_loops, 1 },
- {"unswitch-loops", &flag_unswitch_loops, 1 },
- {"prefetch-loop-arrays", &flag_prefetch_loop_arrays, 1 },
- {"move-all-movables", &flag_move_all_movables, 1 },
- {"reduce-all-givs", &flag_reduce_all_givs, 1 },
- {"writable-strings", &flag_writable_strings, 1 },
- {"peephole", &flag_no_peephole, 0 },
- {"force-mem", &flag_force_mem, 1 },
- {"force-addr", &flag_force_addr, 1 },
- {"function-cse", &flag_no_function_cse, 0 },
- {"inline-functions", &flag_inline_functions, 1 },
- {"keep-inline-functions", &flag_keep_inline_functions, 1 },
- {"inline", &flag_no_inline, 0 },
- {"keep-static-consts", &flag_keep_static_consts, 1 },
- {"syntax-only", &flag_syntax_only, 1 },
- {"shared-data", &flag_shared_data, 1 },
- {"caller-saves", &flag_caller_saves, 1 },
- {"pcc-struct-return", &flag_pcc_struct_return, 1 },
- {"reg-struct-return", &flag_pcc_struct_return, 0 },
- {"delayed-branch", &flag_delayed_branch, 1 },
- {"web", &flag_web, 1},
- {"gcse", &flag_gcse, 1 },
- {"gcse-lm", &flag_gcse_lm, 1 },
- {"gcse-sm", &flag_gcse_sm, 1 },
- {"gcse-las", &flag_gcse_las, 1 },
- {"branch-target-load-optimize", &flag_branch_target_load_optimize, 1 },
- {"branch-target-load-optimize2", &flag_branch_target_load_optimize2, 1 },
- {"loop-optimize", &flag_loop_optimize, 1 },
- {"crossjumping", &flag_crossjumping, 1 },
- {"if-conversion", &flag_if_conversion, 1 },
- {"if-conversion2", &flag_if_conversion2, 1 },
- {"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1 },
- {"rerun-loop-opt", &flag_rerun_loop_opt, 1 },
- {"delete-null-pointer-checks", &flag_delete_null_pointer_checks, 1 },
- {"schedule-insns", &flag_schedule_insns, 1 },
- {"schedule-insns2", &flag_schedule_insns_after_reload, 1 },
- {"sched-interblock",&flag_schedule_interblock, 1 },
- {"sched-spec",&flag_schedule_speculative, 1 },
- {"sched-spec-load",&flag_schedule_speculative_load, 1 },
- {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1 },
- {"sched-stalled-insns", &flag_sched_stalled_insns, 0 },
- {"sched-stalled-insns-dep", &flag_sched_stalled_insns_dep, 1 },
- {"sched2-use-superblocks", &flag_sched2_use_superblocks, 1 },
- {"sched2-use-traces", &flag_sched2_use_traces, 1 },
- {"branch-count-reg",&flag_branch_on_count_reg, 1 },
- {"pic", &flag_pic, 1 },
- {"PIC", &flag_pic, 2 },
- {"pie", &flag_pie, 1 },
- {"PIE", &flag_pie, 2 },
- {"exceptions", &flag_exceptions, 1 },
- {"unwind-tables", &flag_unwind_tables, 1 },
- {"asynchronous-unwind-tables", &flag_asynchronous_unwind_tables, 1 },
- {"non-call-exceptions", &flag_non_call_exceptions, 1 },
- {"profile-arcs", &profile_arc_flag, 1 },
- {"profile-values", &flag_profile_values, 1 },
- {"vpt", &flag_value_profile_transformations, 1 },
- {"test-coverage", &flag_test_coverage, 1 },
- {"branch-probabilities", &flag_branch_probabilities, 1 },
- {"profile", &profile_flag, 1 },
- {"reorder-blocks", &flag_reorder_blocks, 1 },
- {"reorder-functions", &flag_reorder_functions, 1 },
- {"rename-registers", &flag_rename_registers, 1 },
- {"cprop-registers", &flag_cprop_registers, 1 },
- {"common", &flag_no_common, 0 },
- {"inhibit-size-directive", &flag_inhibit_size_directive, 1 },
- {"function-sections", &flag_function_sections, 1 },
- {"data-sections", &flag_data_sections, 1 },
- {"verbose-asm", &flag_verbose_asm, 1 },
- {"regmove", &flag_regmove, 1 },
- {"optimize-register-move", &flag_regmove, 1 },
- {"pack-struct", &flag_pack_struct, 1 },
- {"stack-check", &flag_stack_check, 1 },
- {"argument-alias", &flag_argument_noalias, 0 },
- {"argument-noalias", &flag_argument_noalias, 1 },
- {"argument-noalias-global", &flag_argument_noalias, 2 },
- {"strict-aliasing", &flag_strict_aliasing, 1 },
- {"align-loops", &align_loops, 0 },
- {"align-jumps", &align_jumps, 0 },
- {"align-labels", &align_labels, 0 },
- {"align-functions", &align_functions, 0 },
- {"merge-constants", &flag_merge_constants, 1 },
- {"merge-all-constants", &flag_merge_constants, 2 },
- {"dump-unnumbered", &flag_dump_unnumbered, 1 },
- {"instrument-functions", &flag_instrument_function_entry_exit, 1 },
- {"zero-initialized-in-bss", &flag_zero_initialized_in_bss, 1 },
- {"leading-underscore", &flag_leading_underscore, 1 },
- {"ident", &flag_no_ident, 0 },
- { "peephole2", &flag_peephole2, 1 },
- {"finite-math-only", &flag_finite_math_only, 1 },
- { "guess-branch-probability", &flag_guess_branch_prob, 1 },
- {"math-errno", &flag_errno_math, 1 },
- {"trapping-math", &flag_trapping_math, 1 },
- {"rounding-math", &flag_rounding_math, 1 },
- {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1 },
- {"signaling-nans", &flag_signaling_nans, 1 },
- {"bounds-check", &flag_bounds_check, 1 },
- {"single-precision-constant", &flag_single_precision_constant, 1 },
- {"time-report", &time_report, 1 },
- {"mem-report", &mem_report, 1 },
- { "trapv", &flag_trapv, 1 },
- { "wrapv", &flag_wrapv, 1 },
- { "new-ra", &flag_new_regalloc, 1 }
-};
-
-/* Here is a table, controlled by the tm.h file, listing each -m switch
- and which bits in `target_switches' it should set or clear.
- If VALUE is positive, it is bits to set.
- If VALUE is negative, -VALUE is bits to clear.
- (The sign bit is not used so there is no confusion.) */
-
-static const struct
-{
- const char *const name;
- const int value;
- const char *const description;
-}
-target_switches[] = TARGET_SWITCHES;
-
-/* This table is similar, but allows the switch to have a value. */
-
-#ifdef TARGET_OPTIONS
-static const struct
-{
- const char *const prefix;
- const char **const variable;
- const char *const description;
- const char *const value;
-}
-target_options[] = TARGET_OPTIONS;
-#endif
-
-/* Nonzero means warn about function definitions that default the return type
- or that use a null return and have a return-type other than void. */
-
-int warn_return_type;
-
/* Output files for assembler code (real compiler output)
and debugging dumps. */
FILE *asm_out_file;
FILE *aux_info_file;
-FILE *rtl_dump_file = NULL;
-FILE *cgraph_dump_file = NULL;
+FILE *dump_file = NULL;
+const char *dump_file_name;
/* The current working directory of a translation. It's generally the
directory from which compilation was initiated, but a preprocessed
@@ -1219,7 +419,12 @@ bool
set_src_pwd (const char *pwd)
{
if (src_pwd)
- return false;
+ {
+ if (strcmp (src_pwd, pwd) == 0)
+ return true;
+ else
+ return false;
+ }
src_pwd = xstrdup (pwd);
return true;
@@ -1233,7 +438,11 @@ const char *
get_src_pwd (void)
{
if (! src_pwd)
- src_pwd = getpwd ();
+ {
+ src_pwd = getpwd ();
+ if (!src_pwd)
+ src_pwd = ".";
+ }
return src_pwd;
}
@@ -1246,9 +455,9 @@ announce_function (tree decl)
if (!quiet_flag)
{
if (rtl_dump_and_exit)
- verbatim ("%s ", IDENTIFIER_POINTER (DECL_NAME (decl)));
+ fprintf (stderr, "%s ", IDENTIFIER_POINTER (DECL_NAME (decl)));
else
- verbatim (" %s", (*lang_hooks.decl_printable_name) (decl, 2));
+ fprintf (stderr, " %s", lang_hooks.decl_printable_name (decl, 2));
fflush (stderr);
pp_needs_newline (global_dc->printer) = true;
diagnostic_set_last_function (global_dc);
@@ -1313,45 +522,71 @@ read_integral_parameter (const char *p, const char *pname, const int defval)
if (*endp != 0)
{
if (pname != 0)
- error ("invalid option argument `%s'", pname);
+ error ("invalid option argument %qs", pname);
return defval;
}
return atoi (p);
}
-/* Return the logarithm of X, base 2, considering X unsigned,
- if X is a power of 2. Otherwise, returns -1.
+/* When compiling with a recent enough GCC, we use the GNU C "extern inline"
+ for floor_log2 and exact_log2; see toplev.h. That construct, however,
+ conflicts with the ISO C++ One Definition Rule. */
- This should be used via the `exact_log2' macro. */
+#if GCC_VERSION < 3004 || !defined (__cplusplus)
+
+/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
+ If X is 0, return -1. */
int
-exact_log2_wide (unsigned HOST_WIDE_INT x)
+floor_log2 (unsigned HOST_WIDE_INT x)
{
- int log = 0;
- /* Test for 0 or a power of 2. */
- if (x == 0 || x != (x & -x))
+ int t = 0;
+
+ if (x == 0)
return -1;
- while ((x >>= 1) != 0)
- log++;
- return log;
-}
-/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
- If X is 0, return -1.
+#ifdef CLZ_HWI
+ t = HOST_BITS_PER_WIDE_INT - 1 - (int) CLZ_HWI (x);
+#else
+ if (HOST_BITS_PER_WIDE_INT > 64)
+ if (x >= (unsigned HOST_WIDE_INT) 1 << (t + 64))
+ t += 64;
+ if (HOST_BITS_PER_WIDE_INT > 32)
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 32))
+ t += 32;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 16))
+ t += 16;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 8))
+ t += 8;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 4))
+ t += 4;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 2))
+ t += 2;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 1))
+ t += 1;
+#endif
+
+ return t;
+}
- This should be used via the floor_log2 macro. */
+/* Return the logarithm of X, base 2, considering X unsigned,
+ if X is a power of 2. Otherwise, returns -1. */
int
-floor_log2_wide (unsigned HOST_WIDE_INT x)
+exact_log2 (unsigned HOST_WIDE_INT x)
{
- int log = -1;
- while (x != 0)
- log++,
- x >>= 1;
- return log;
+ if (x != (x & -x))
+ return -1;
+#ifdef CTZ_HWI
+ return x ? CTZ_HWI (x) : -1;
+#else
+ return floor_log2 (x);
+#endif
}
+#endif /* GCC_VERSION < 3004 || !defined (__cplusplus) */
+
/* Handler for fatal signals, such as SIGSEGV. These are transformed
into ICE messages, which is much more user friendly. In case the
error printer crashes, reset the signal to prevent infinite recursion. */
@@ -1360,6 +595,15 @@ static void
crash_signal (int signo)
{
signal (signo, SIG_DFL);
+
+ /* If we crashed while processing an ASM statement, then be a little more
+ graceful. It's most likely the user's fault. */
+ if (this_is_asm_operands)
+ {
+ output_operand_lossage ("unrecoverable error");
+ exit (FATAL_EXIT_CODE);
+ }
+
internal_error ("%s", strsignal (signo));
}
@@ -1462,94 +706,88 @@ output_file_directive (FILE *asm_file, const char *input_name)
#endif
}
-/* Routine to open a dump file. Return true if the dump file is enabled. */
+/* A subroutine of wrapup_global_declarations. We've come to the end of
+ the compilation unit. All deferred variables should be undeferred,
+ and all incomplete decls should be finalized. */
-static int
-open_dump_file (enum dump_file_index index, tree decl)
+void
+wrapup_global_declaration_1 (tree decl)
{
- char *dump_name;
- const char *open_arg;
- char seq[16];
-
- if (! dump_file[index].enabled)
- return 0;
-
- timevar_push (TV_DUMP);
- if (rtl_dump_file != NULL)
- fclose (rtl_dump_file);
-
- sprintf (seq, DUMPFILE_FORMAT, index);
-
- if (! dump_file[index].initialized)
- {
- /* If we've not initialized the files, do so now. */
- if (graph_dump_format != no_graph
- && dump_file[index].graph_dump_p)
- {
- dump_name = concat (seq, dump_file[index].extension, NULL);
- clean_graph_dump_file (dump_base_name, dump_name);
- free (dump_name);
- }
- dump_file[index].initialized = 1;
- open_arg = "w";
- }
- else
- open_arg = "a";
-
- dump_name = concat (dump_base_name, seq,
- dump_file[index].extension, NULL);
-
- rtl_dump_file = fopen (dump_name, open_arg);
- if (rtl_dump_file == NULL)
- fatal_error ("can't open %s: %m", dump_name);
-
- free (dump_name);
-
- if (decl)
- fprintf (rtl_dump_file, "\n;; Function %s%s\n\n",
- (*lang_hooks.decl_printable_name) (decl, 2),
- cfun->function_frequency == FUNCTION_FREQUENCY_HOT
- ? " (hot)"
- : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED
- ? " (unlikely executed)"
- : "");
+ /* We're not deferring this any longer. Assignment is conditional to
+ avoid needlessly dirtying PCH pages. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS)
+ && DECL_DEFER_OUTPUT (decl) != 0)
+ DECL_DEFER_OUTPUT (decl) = 0;
- timevar_pop (TV_DUMP);
- return 1;
+ if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0)
+ lang_hooks.finish_incomplete_decl (decl);
}
-/* Routine to close a dump file. */
+/* A subroutine of wrapup_global_declarations. Decide whether or not DECL
+ needs to be output. Return true if it is output. */
-static void
-close_dump_file (enum dump_file_index index,
- void (*func) (FILE *, rtx),
- rtx insns)
+bool
+wrapup_global_declaration_2 (tree decl)
{
- if (! rtl_dump_file)
- return;
-
- timevar_push (TV_DUMP);
- if (insns
- && graph_dump_format != no_graph
- && dump_file[index].graph_dump_p)
- {
- char seq[16];
- char *suffix;
+ if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
+ return false;
- sprintf (seq, DUMPFILE_FORMAT, index);
- suffix = concat (seq, dump_file[index].extension, NULL);
- print_rtl_graph_with_bb (dump_base_name, suffix, insns);
- free (suffix);
+ /* Don't write out static consts, unless we still need them.
+
+ We also keep static consts if not optimizing (for debugging),
+ unless the user specified -fno-keep-static-consts.
+ ??? They might be better written into the debug information.
+ This is possible when using DWARF.
+
+ A language processor that wants static constants to be always
+ written out (even if it is not used) is responsible for
+ calling rest_of_decl_compilation itself. E.g. the C front-end
+ calls rest_of_decl_compilation from finish_decl.
+ One motivation for this is that is conventional in some
+ environments to write things like:
+ static const char rcsid[] = "... version string ...";
+ intending to force the string to be in the executable.
+
+ A language processor that would prefer to have unneeded
+ static constants "optimized away" would just defer writing
+ them out until here. E.g. C++ does this, because static
+ constants are often defined in header files.
+
+ ??? A tempting alternative (for both C and C++) would be
+ to force a constant to be written if and only if it is
+ defined in a main file, as opposed to an include file. */
+
+ if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+ {
+ struct cgraph_varpool_node *node;
+ bool needed = true;
+ node = cgraph_varpool_node (decl);
+
+ if (node->finalized)
+ needed = false;
+ else if (node->alias)
+ needed = false;
+ else if (!cgraph_global_info_ready
+ && (TREE_USED (decl)
+ || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
+ /* needed */;
+ else if (node->needed)
+ /* needed */;
+ else if (DECL_COMDAT (decl))
+ needed = false;
+ else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
+ && (optimize || !flag_keep_static_consts
+ || DECL_ARTIFICIAL (decl)))
+ needed = false;
+
+ if (needed)
+ {
+ rest_of_decl_compilation (decl, 1, 1);
+ return true;
+ }
}
- if (func && insns)
- func (rtl_dump_file, insns);
-
- fflush (rtl_dump_file);
- fclose (rtl_dump_file);
-
- rtl_dump_file = NULL;
- timevar_pop (TV_DUMP);
+ return false;
}
/* Do any final processing required for the declarations in VEC, of
@@ -1557,185 +795,107 @@ close_dump_file (enum dump_file_index index,
that have been deferred until this point, but which are required.
Returns nonzero if anything was put out. */
-int
+bool
wrapup_global_declarations (tree *vec, int len)
{
- tree decl;
+ bool reconsider, output_something = false;
int i;
- int reconsider;
- int output_something = 0;
for (i = 0; i < len; i++)
- {
- decl = vec[i];
-
- /* We're not deferring this any longer. Assignment is
- conditional to avoid needlessly dirtying PCH pages. */
- if (DECL_DEFER_OUTPUT (decl) != 0)
- DECL_DEFER_OUTPUT (decl) = 0;
-
- if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0)
- (*lang_hooks.finish_incomplete_decl) (decl);
- }
+ wrapup_global_declaration_1 (vec[i]);
/* Now emit any global variables or functions that we have been
putting off. We need to loop in case one of the things emitted
here references another one which comes earlier in the list. */
do
{
- reconsider = 0;
+ reconsider = false;
for (i = 0; i < len; i++)
- {
- decl = vec[i];
-
- if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
- continue;
-
- /* Don't write out static consts, unless we still need them.
-
- We also keep static consts if not optimizing (for debugging),
- unless the user specified -fno-keep-static-consts.
- ??? They might be better written into the debug information.
- This is possible when using DWARF.
-
- A language processor that wants static constants to be always
- written out (even if it is not used) is responsible for
- calling rest_of_decl_compilation itself. E.g. the C front-end
- calls rest_of_decl_compilation from finish_decl.
- One motivation for this is that is conventional in some
- environments to write things like:
- static const char rcsid[] = "... version string ...";
- intending to force the string to be in the executable.
-
- A language processor that would prefer to have unneeded
- static constants "optimized away" would just defer writing
- them out until here. E.g. C++ does this, because static
- constants are often defined in header files.
-
- ??? A tempting alternative (for both C and C++) would be
- to force a constant to be written if and only if it is
- defined in a main file, as opposed to an include file. */
-
- if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
- {
- bool needed = 1;
-
- if (flag_unit_at_a_time
- && cgraph_varpool_node (decl)->finalized)
- needed = 0;
- else if ((flag_unit_at_a_time && !cgraph_global_info_ready)
- && (TREE_USED (decl)
- || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
- /* needed */;
- else if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
- /* needed */;
- else if (DECL_COMDAT (decl))
- needed = 0;
- else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
- && (optimize || !flag_keep_static_consts
- || DECL_ARTIFICIAL (decl)))
- needed = 0;
-
- if (needed)
- {
- reconsider = 1;
- rest_of_decl_compilation (decl, NULL, 1, 1);
- }
- }
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl) != 0
- && DECL_SAVED_INSNS (decl) != 0
- && DECL_SAVED_INSNS (decl)->saved_for_inline
- && (flag_keep_inline_functions
- || (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
- {
- reconsider = 1;
- output_inline_function (decl);
- }
- }
-
+ reconsider |= wrapup_global_declaration_2 (vec[i]);
if (reconsider)
- output_something = 1;
+ output_something = true;
}
while (reconsider);
return output_something;
}
+/* A subroutine of check_global_declarations. Issue appropriate warnings
+ for the global declaration DECL. */
+
+void
+check_global_declaration_1 (tree decl)
+{
+ /* Warn about any function declared static but not defined. We don't
+ warn about variables, because many programs have static variables
+ that exist only to get some text into the object file. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INITIAL (decl) == 0
+ && DECL_EXTERNAL (decl)
+ && ! DECL_ARTIFICIAL (decl)
+ && ! TREE_NO_WARNING (decl)
+ && ! TREE_PUBLIC (decl)
+ && (warn_unused_function
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ {
+ if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ pedwarn ("%q+F used but never defined", decl);
+ else
+ warning (0, "%q+F declared %<static%> but never defined", decl);
+ /* This symbol is effectively an "extern" declaration now. */
+ TREE_PUBLIC (decl) = 1;
+ assemble_external (decl);
+ }
+
+ /* Warn about static fns or vars defined but not used. */
+ if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL)
+ /* We don't warn about "static const" variables because the
+ "rcs_id" idiom uses that construction. */
+ || (warn_unused_variable
+ && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
+ && ! DECL_IN_SYSTEM_HEADER (decl)
+ && ! TREE_USED (decl)
+ /* The TREE_USED bit for file-scope decls is kept in the identifier,
+ to handle multiple external decls in different scopes. */
+ && ! (DECL_NAME (decl) && TREE_USED (DECL_NAME (decl)))
+ && ! DECL_EXTERNAL (decl)
+ && ! TREE_PUBLIC (decl)
+ /* A volatile variable might be used in some non-obvious way. */
+ && ! TREE_THIS_VOLATILE (decl)
+ /* Global register variables must be declared to reserve them. */
+ && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+ /* Otherwise, ask the language. */
+ && lang_hooks.decls.warn_unused_global (decl))
+ warning (0, "%q+D defined but not used", decl);
+}
+
/* Issue appropriate warnings for the global declarations in VEC (of
- which there are LEN). Output debugging information for them. */
+ which there are LEN). */
void
check_global_declarations (tree *vec, int len)
{
- tree decl;
int i;
for (i = 0; i < len; i++)
- {
- decl = vec[i];
-
- if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
- && ! TREE_ASM_WRITTEN (decl))
- /* Cancel the RTL for this decl so that, if debugging info
- output for global variables is still to come,
- this one will be omitted. */
- SET_DECL_RTL (decl, NULL_RTX);
-
- /* Warn about any function
- declared static but not defined.
- We don't warn about variables,
- because many programs have static variables
- that exist only to get some text into the object file. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && (warn_unused_function
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
- && DECL_INITIAL (decl) == 0
- && DECL_EXTERNAL (decl)
- && ! DECL_ARTIFICIAL (decl)
- && ! TREE_PUBLIC (decl))
- {
- if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
- pedwarn ("%J'%F' used but never defined", decl, decl);
- else
- warning ("%J'%F' declared `static' but never defined", decl, decl);
- /* This symbol is effectively an "extern" declaration now. */
- TREE_PUBLIC (decl) = 1;
- assemble_external (decl);
- }
+ check_global_declaration_1 (vec[i]);
+}
- /* Warn about static fns or vars defined but not used. */
- if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL)
- /* We don't warn about "static const" variables because the
- "rcs_id" idiom uses that construction. */
- || (warn_unused_variable
- && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
- && ! DECL_IN_SYSTEM_HEADER (decl)
- && ! TREE_USED (decl)
- /* The TREE_USED bit for file-scope decls is kept in the identifier,
- to handle multiple external decls in different scopes. */
- && ! TREE_USED (DECL_NAME (decl))
- && ! DECL_EXTERNAL (decl)
- && ! TREE_PUBLIC (decl)
- /* A volatile variable might be used in some non-obvious way. */
- && ! TREE_THIS_VOLATILE (decl)
- /* Global register variables must be declared to reserve them. */
- && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
- /* Otherwise, ask the language. */
- && (*lang_hooks.decls.warn_unused_global) (decl))
- warning ("%J'%D' defined but not used", decl, decl);
-
- /* Avoid confusing the debug information machinery when there are
- errors. */
- if (errorcount == 0 && sorrycount == 0)
- {
- timevar_push (TV_SYMOUT);
- (*debug_hooks->global_decl) (decl);
- timevar_pop (TV_SYMOUT);
- }
- }
+/* Emit debugging information for all global declarations in VEC. */
+
+void
+emit_debug_global_declarations (tree *vec, int len)
+{
+ int i;
+
+ /* Avoid confusing the debug information machinery when there are errors. */
+ if (errorcount != 0 || sorrycount != 0)
+ return;
+
+ timevar_push (TV_SYMOUT);
+ for (i = 0; i < len; i++)
+ debug_hooks->global_decl (vec[i]);
+ timevar_pop (TV_SYMOUT);
}
/* Warn about a use of an identifier which was marked deprecated. */
@@ -1746,33 +906,47 @@ warn_deprecated_use (tree node)
return;
if (DECL_P (node))
- warning ("`%s' is deprecated (declared at %s:%d)",
- IDENTIFIER_POINTER (DECL_NAME (node)),
- DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node));
+ {
+ expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (node));
+ warning (OPT_Wdeprecated_declarations,
+ "%qs is deprecated (declared at %s:%d)",
+ IDENTIFIER_POINTER (DECL_NAME (node)),
+ xloc.file, xloc.line);
+ }
else if (TYPE_P (node))
{
const char *what = NULL;
tree decl = TYPE_STUB_DECL (node);
- if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
- what = IDENTIFIER_POINTER (TYPE_NAME (node));
- else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
- && DECL_NAME (TYPE_NAME (node)))
- what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node)));
+ if (TYPE_NAME (node))
+ {
+ if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
+ what = IDENTIFIER_POINTER (TYPE_NAME (node));
+ else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (node)))
+ what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node)));
+ }
- if (what)
+ if (decl)
{
- if (decl)
- warning ("`%s' is deprecated (declared at %s:%d)", what,
- DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
+ expanded_location xloc
+ = expand_location (DECL_SOURCE_LOCATION (decl));
+ if (what)
+ warning (OPT_Wdeprecated_declarations,
+ "%qs is deprecated (declared at %s:%d)", what,
+ xloc.file, xloc.line);
else
- warning ("`%s' is deprecated", what);
+ warning (OPT_Wdeprecated_declarations,
+ "type is deprecated (declared at %s:%d)",
+ xloc.file, xloc.line);
}
- else if (decl)
- warning ("type is deprecated (declared at %s:%d)",
- DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
else
- warning ("type is deprecated");
+ {
+ if (what)
+ warning (OPT_Wdeprecated_declarations, "%qs is deprecated", what);
+ else
+ warning (OPT_Wdeprecated_declarations, "type is deprecated");
+ }
}
}
@@ -1781,17 +955,30 @@ warn_deprecated_use (tree node)
INPUT_LOCATION accordingly. */
void
+#ifdef USE_MAPPED_LOCATION
+push_srcloc (location_t fline)
+#else
push_srcloc (const char *file, int line)
+#endif
{
struct file_stack *fs;
- fs = xmalloc (sizeof (struct file_stack));
+ gcc_assert (!input_file_stack_restored);
+ if (input_file_stack_tick == (int) ((1U << INPUT_FILE_STACK_BITS) - 1))
+ sorry ("GCC supports only %d input file changes", input_file_stack_tick);
+
+ fs = XNEW (struct file_stack);
fs->location = input_location;
fs->next = input_file_stack;
+#ifdef USE_MAPPED_LOCATION
+ input_location = fline;
+#else
input_filename = file;
input_line = line;
+#endif
input_file_stack = fs;
input_file_stack_tick++;
+ VEC_safe_push (fs_p, heap, input_file_stack_history, input_file_stack);
}
/* Pop the top entry off the stack of presently open source files.
@@ -1803,11 +990,30 @@ pop_srcloc (void)
{
struct file_stack *fs;
+ gcc_assert (!input_file_stack_restored);
+ if (input_file_stack_tick == (int) ((1U << INPUT_FILE_STACK_BITS) - 1))
+ sorry ("GCC supports only %d input file changes", input_file_stack_tick);
+
fs = input_file_stack;
input_location = fs->location;
input_file_stack = fs->next;
- free (fs);
input_file_stack_tick++;
+ VEC_safe_push (fs_p, heap, input_file_stack_history, input_file_stack);
+}
+
+/* Restore the input file stack to its state as of TICK, for the sake
+ of diagnostics after processing the whole input. Once this has
+ been called, push_srcloc and pop_srcloc may no longer be
+ called. */
+void
+restore_input_file_stack (int tick)
+{
+ if (tick == 0)
+ input_file_stack = NULL;
+ else
+ input_file_stack = VEC_index (fs_p, input_file_stack_history, tick - 1);
+ input_file_stack_tick = tick;
+ input_file_stack_restored = true;
}
/* Compile an entire translation unit. Write a file of assembly
@@ -1818,6 +1024,7 @@ compile_file (void)
{
/* Initialize yet another pass. */
+ init_cgraph ();
init_final (main_input_filename);
coverage_init (aux_base_name);
@@ -1825,28 +1032,35 @@ compile_file (void)
/* Call the parser, which parses the entire file (calling
rest_of_compilation for each function). */
- (*lang_hooks.parse_file) (set_yydebug);
+ lang_hooks.parse_file (set_yydebug);
/* In case there were missing block closers,
get us back to the global binding level. */
- (*lang_hooks.clear_binding_stack) ();
+ lang_hooks.clear_binding_stack ();
/* Compilation is now finished except for writing
what's left of the symbol table output. */
timevar_pop (TV_PARSE);
- if (flag_syntax_only)
+ if (flag_syntax_only || errorcount || sorrycount)
return;
- (*lang_hooks.decls.final_write_globals)();
-
+ lang_hooks.decls.final_write_globals ();
cgraph_varpool_assemble_pending_decls ();
+ finish_aliases_2 ();
/* This must occur after the loop to output deferred functions.
Else the coverage initializer would not be emitted if all the
functions in this compilation unit were deferred. */
coverage_finish ();
+ /* Likewise for mudflap static object registrations. */
+ if (flag_mudflap)
+ mudflap_finish_file ();
+
+ output_shared_constant_pool ();
+ output_object_blocks ();
+
/* Write out any pending weak symbol declarations. */
weak_finish ();
@@ -1854,7 +1068,7 @@ compile_file (void)
/* Do dbx symbols. */
timevar_push (TV_SYMOUT);
-#ifdef DWARF2_UNWIND_INFO
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
dwarf2out_frame_finish ();
#endif
@@ -1866,21 +1080,10 @@ compile_file (void)
dw2_output_indirect_constants ();
- /* Flush any pending equate directives. */
- process_pending_assemble_output_defs ();
-
- if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
- {
- timevar_push (TV_DUMP);
- open_dump_file (DFI_bp, NULL);
-
- end_branch_prob ();
-
- close_dump_file (DFI_bp, NULL, NULL_RTX);
- timevar_pop (TV_DUMP);
- }
-
- targetm.asm_out.file_end ();
+ /* Flush any pending external directives. cgraph did this for
+ assemble_external calls from the front end, but the RTL
+ expander can also generate them. */
+ process_pending_assemble_externals ();
/* Attach a special .ident directive to the end of the file to identify
the version of GCC which compiled this code. The format of the .ident
@@ -1891,1881 +1094,10 @@ compile_file (void)
IDENT_ASM_OP, version_string);
#endif
- if (optimize > 0 && open_dump_file (DFI_combine, NULL))
- {
- timevar_push (TV_DUMP);
- dump_combine_total_stats (rtl_dump_file);
- close_dump_file (DFI_combine, NULL, NULL_RTX);
- timevar_pop (TV_DUMP);
- }
-}
-
-/* This is called from various places for FUNCTION_DECL, VAR_DECL,
- and TYPE_DECL nodes.
-
- This does nothing for local (non-static) variables, unless the
- variable is a register variable with an ASMSPEC. In that case, or
- if the variable is not an automatic, it sets up the RTL and
- outputs any assembler code (label definition, storage allocation
- and initialization).
-
- DECL is the declaration. If ASMSPEC is nonzero, it specifies
- the assembler symbol name to be used. TOP_LEVEL is nonzero
- if this declaration is not within a function. */
-
-void
-rest_of_decl_compilation (tree decl,
- const char *asmspec,
- int top_level,
- int at_end)
-{
- /* We deferred calling assemble_alias so that we could collect
- other attributes such as visibility. Emit the alias now. */
- {
- tree alias;
- alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
- if (alias)
- {
- alias = TREE_VALUE (TREE_VALUE (alias));
- alias = get_identifier (TREE_STRING_POINTER (alias));
- assemble_alias (decl, alias);
- }
- }
-
- /* Forward declarations for nested functions are not "external",
- but we need to treat them as if they were. */
- if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
- || TREE_CODE (decl) == FUNCTION_DECL)
- {
- timevar_push (TV_VARCONST);
-
- if (asmspec)
- make_decl_rtl (decl, asmspec);
-
- /* Don't output anything when a tentative file-scope definition
- is seen. But at end of compilation, do output code for them.
-
- We do output all variables when unit-at-a-time is active and rely on
- callgraph code to defer them except for forward declarations
- (see gcc.c-torture/compile/920624-1.c) */
- if ((at_end
- || !DECL_DEFER_OUTPUT (decl)
- || (flag_unit_at_a_time && DECL_INITIAL (decl)))
- && !DECL_EXTERNAL (decl))
- {
- if (flag_unit_at_a_time && !cgraph_global_info_ready
- && TREE_CODE (decl) != FUNCTION_DECL && top_level)
- cgraph_varpool_finalize_decl (decl);
- else
- assemble_variable (decl, top_level, at_end, 0);
- }
-
-#ifdef ASM_FINISH_DECLARE_OBJECT
- if (decl == last_assemble_variable_decl)
- {
- ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
- top_level, at_end);
- }
-#endif
-
- timevar_pop (TV_VARCONST);
- }
- else if (DECL_REGISTER (decl) && asmspec != 0)
- {
- if (decode_reg_name (asmspec) >= 0)
- {
- SET_DECL_RTL (decl, NULL_RTX);
- make_decl_rtl (decl, asmspec);
- }
- else
- {
- error ("invalid register name `%s' for register variable", asmspec);
- DECL_REGISTER (decl) = 0;
- if (!top_level)
- expand_decl (decl);
- }
- }
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
- else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- && TREE_CODE (decl) == TYPE_DECL)
- {
- timevar_push (TV_SYMOUT);
- dbxout_symbol (decl, 0);
- timevar_pop (TV_SYMOUT);
- }
-#endif
-#ifdef SDB_DEBUGGING_INFO
- else if (write_symbols == SDB_DEBUG && top_level
- && TREE_CODE (decl) == TYPE_DECL)
- {
- timevar_push (TV_SYMOUT);
- sdbout_symbol (decl, 0);
- timevar_pop (TV_SYMOUT);
- }
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- else if ((write_symbols == DWARF2_DEBUG
- || write_symbols == VMS_AND_DWARF2_DEBUG)
- && top_level
- && TREE_CODE (decl) == TYPE_DECL)
- {
- timevar_push (TV_SYMOUT);
- dwarf2out_decl (decl);
- timevar_pop (TV_SYMOUT);
- }
-#endif
-}
-
-/* Called after finishing a record, union or enumeral type. */
-
-void
-rest_of_type_compilation (
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) \
- || defined (SDB_DEBUGGING_INFO) || defined (DWARF2_DEBUGGING_INFO)
- tree type,
- int toplev
-#else
- tree type ATTRIBUTE_UNUSED,
- int toplev ATTRIBUTE_UNUSED
-#endif
- )
-{
- /* Avoid confusing the debug information machinery when there are
- errors. */
- if (errorcount != 0 || sorrycount != 0)
- return;
-
- timevar_push (TV_SYMOUT);
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
- if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- dbxout_symbol (TYPE_STUB_DECL (type), !toplev);
-#endif
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG)
- sdbout_symbol (TYPE_STUB_DECL (type), !toplev);
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- if ((write_symbols == DWARF2_DEBUG
- || write_symbols == VMS_AND_DWARF2_DEBUG)
- && toplev)
- dwarf2out_decl (TYPE_STUB_DECL (type));
-#endif
- timevar_pop (TV_SYMOUT);
-}
-
-/* Turn the RTL into assembly. */
-static void
-rest_of_handle_final (tree decl, rtx insns)
-{
- timevar_push (TV_FINAL);
- {
- rtx x;
- const char *fnname;
-
- /* Get the function's name, as described by its RTL. This may be
- different from the DECL_NAME name used in the source file. */
-
- x = DECL_RTL (decl);
- if (GET_CODE (x) != MEM)
- abort ();
- x = XEXP (x, 0);
- if (GET_CODE (x) != SYMBOL_REF)
- abort ();
- fnname = XSTR (x, 0);
-
- assemble_start_function (decl, fnname);
- final_start_function (insns, asm_out_file, optimize);
- final (insns, asm_out_file, optimize, 0);
- final_end_function ();
-
-#ifdef IA64_UNWIND_INFO
- /* ??? The IA-64 ".handlerdata" directive must be issued before
- the ".endp" directive that closes the procedure descriptor. */
- output_function_exception_table ();
-#endif
-
- assemble_end_function (decl, fnname);
-
-#ifndef IA64_UNWIND_INFO
- /* Otherwise, it feels unclean to switch sections in the middle. */
- output_function_exception_table ();
-#endif
-
- if (! quiet_flag)
- fflush (asm_out_file);
-
- /* Release all memory allocated by flow. */
- free_basic_block_vars (0);
-
- /* Release all memory held by regsets now. */
- regset_release_memory ();
- }
- timevar_pop (TV_FINAL);
-
- ggc_collect ();
-}
-
-#ifdef DELAY_SLOTS
-/* Run delay slot optimization. */
-static void
-rest_of_handle_delay_slots (tree decl, rtx insns)
-{
- timevar_push (TV_DBR_SCHED);
- open_dump_file (DFI_dbr, decl);
-
- dbr_schedule (insns, rtl_dump_file);
-
- close_dump_file (DFI_dbr, print_rtl, insns);
- timevar_pop (TV_DBR_SCHED);
-
- ggc_collect ();
-}
-#endif
-
-#ifdef STACK_REGS
-/* Convert register usage from flat register file usage to a stack
- register file. */
-static void
-rest_of_handle_stack_regs (tree decl, rtx insns)
-{
-#if defined (HAVE_ATTR_length)
- /* If flow2 creates new instructions which need splitting
- and scheduling after reload is not done, they might not be
- split until final which doesn't allow splitting
- if HAVE_ATTR_length. */
-#ifdef INSN_SCHEDULING
- if (optimize && !flag_schedule_insns_after_reload)
-#else
- if (optimize)
-#endif
- {
- timevar_push (TV_SHORTEN_BRANCH);
- split_all_insns (1);
- timevar_pop (TV_SHORTEN_BRANCH);
- }
-#endif
-
- timevar_push (TV_REG_STACK);
- open_dump_file (DFI_stack, decl);
-
- if (reg_to_stack (insns, rtl_dump_file) && optimize)
- {
- if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK
- | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0))
- && flag_reorder_blocks)
- {
- reorder_basic_blocks (0);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
- }
- }
-
- close_dump_file (DFI_stack, print_rtl_with_bb, insns);
- timevar_pop (TV_REG_STACK);
-
- ggc_collect ();
-}
-#endif
-
-
-/* Machine independent reorg pass. */
-static void
-rest_of_handle_machine_reorg (tree decl, rtx insns)
-{
- timevar_push (TV_MACH_DEP);
- open_dump_file (DFI_mach, decl);
-
- (*targetm.machine_dependent_reorg) ();
-
- close_dump_file (DFI_mach, print_rtl, insns);
- timevar_pop (TV_MACH_DEP);
-
- ggc_collect ();
-}
-
-
-/* Run new register allocator. Return TRUE if we must exit
- rest_of_compilation upon return. */
-static bool
-rest_of_handle_new_regalloc (tree decl, rtx insns)
-{
- int failure;
-
- delete_trivially_dead_insns (insns, max_reg_num ());
- reg_alloc ();
-
- timevar_pop (TV_LOCAL_ALLOC);
- if (dump_file[DFI_lreg].enabled)
- {
- timevar_push (TV_DUMP);
-
- close_dump_file (DFI_lreg, NULL, NULL);
- timevar_pop (TV_DUMP);
- }
-
- /* XXX clean up the whole mess to bring live info in shape again. */
- timevar_push (TV_GLOBAL_ALLOC);
- open_dump_file (DFI_greg, decl);
-
- build_insn_chain (insns);
- failure = reload (insns, 0);
-
- timevar_pop (TV_GLOBAL_ALLOC);
-
- if (dump_file[DFI_greg].enabled)
- {
- timevar_push (TV_DUMP);
-
- dump_global_regs (rtl_dump_file);
-
- close_dump_file (DFI_greg, print_rtl_with_bb, insns);
- timevar_pop (TV_DUMP);
- }
-
- if (failure)
- return true;
-
- reload_completed = 1;
-
- return false;
-}
-
-/* Run old register allocator. Return TRUE if we must exit
- rest_of_compilation upon return. */
-static bool
-rest_of_handle_old_regalloc (tree decl, rtx insns)
-{
- int failure;
- int rebuild_notes;
-
- /* Allocate the reg_renumber array. */
- allocate_reg_info (max_regno, FALSE, TRUE);
-
- /* And the reg_equiv_memory_loc array. */
- reg_equiv_memory_loc = xcalloc (max_regno, sizeof (rtx));
-
- allocate_initial_values (reg_equiv_memory_loc);
-
- regclass (insns, max_reg_num (), rtl_dump_file);
- rebuild_notes = local_alloc ();
-
- timevar_pop (TV_LOCAL_ALLOC);
-
- /* Local allocation may have turned an indirect jump into a direct
- jump. If so, we must rebuild the JUMP_LABEL fields of jumping
- instructions. */
- if (rebuild_notes)
- {
- timevar_push (TV_JUMP);
-
- rebuild_jump_labels (insns);
- purge_all_dead_edges (0);
-
- timevar_pop (TV_JUMP);
- }
-
- if (dump_file[DFI_lreg].enabled)
- {
- timevar_push (TV_DUMP);
-
- dump_flow_info (rtl_dump_file);
- dump_local_alloc (rtl_dump_file);
-
- close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
- timevar_pop (TV_DUMP);
- }
-
- ggc_collect ();
-
- timevar_push (TV_GLOBAL_ALLOC);
- open_dump_file (DFI_greg, decl);
-
- /* If optimizing, allocate remaining pseudo-regs. Do the reload
- pass fixing up any insns that are invalid. */
-
- if (optimize)
- failure = global_alloc (rtl_dump_file);
- else
- {
- build_insn_chain (insns);
- failure = reload (insns, 0);
- }
-
- timevar_pop (TV_GLOBAL_ALLOC);
-
- if (dump_file[DFI_greg].enabled)
- {
- timevar_push (TV_DUMP);
-
- dump_global_regs (rtl_dump_file);
-
- close_dump_file (DFI_greg, print_rtl_with_bb, insns);
- timevar_pop (TV_DUMP);
- }
-
- return failure;
-}
-
-/* Run the regrename and cprop passes. */
-static void
-rest_of_handle_regrename (tree decl, rtx insns)
-{
- timevar_push (TV_RENAME_REGISTERS);
- open_dump_file (DFI_rnreg, decl);
-
- if (flag_rename_registers)
- regrename_optimize ();
- if (flag_cprop_registers)
- copyprop_hardreg_forward ();
-
- close_dump_file (DFI_rnreg, print_rtl_with_bb, insns);
- timevar_pop (TV_RENAME_REGISTERS);
-}
-
-/* Reorder basic blocks. */
-static void
-rest_of_handle_reorder_blocks (tree decl, rtx insns)
-{
- bool changed;
- unsigned int liveness_flags;
-
- open_dump_file (DFI_bbro, decl);
-
- /* Last attempt to optimize CFG, as scheduling, peepholing and insn
- splitting possibly introduced more crossjumping opportunities. */
- liveness_flags = (!HAVE_conditional_execution ? CLEANUP_UPDATE_LIFE : 0);
- changed = cleanup_cfg (CLEANUP_EXPENSIVE | liveness_flags);
-
- if (flag_sched2_use_traces && flag_schedule_insns_after_reload)
- tracer (liveness_flags);
- if (flag_reorder_blocks)
- reorder_basic_blocks (liveness_flags);
- if (flag_reorder_blocks
- || (flag_sched2_use_traces && flag_schedule_insns_after_reload))
- changed |= cleanup_cfg (CLEANUP_EXPENSIVE | liveness_flags);
-
- /* On conditional execution targets we can not update the life cheaply, so
- we deffer the updating to after both cleanups. This may lose some cases
- but should not be terribly bad. */
- if (changed && HAVE_conditional_execution)
- update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_DEATH_NOTES | PROP_REG_INFO);
- close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
-}
-
-#ifdef INSN_SCHEDULING
-/* Run instruction scheduler. */
-static void
-rest_of_handle_sched (tree decl, rtx insns)
-{
- timevar_push (TV_SCHED);
-
- /* Print function header into sched dump now
- because doing the sched analysis makes some of the dump. */
- if (optimize > 0 && flag_schedule_insns)
- {
- open_dump_file (DFI_sched, decl);
-
- /* Do control and data sched analysis,
- and write some of the results to dump file. */
-
- schedule_insns (rtl_dump_file);
-
- close_dump_file (DFI_sched, print_rtl_with_bb, insns);
- }
- timevar_pop (TV_SCHED);
-
- ggc_collect ();
-}
-
-/* Run second scheduling pass after reload. */
-static void
-rest_of_handle_sched2 (tree decl, rtx insns)
-{
- timevar_push (TV_SCHED2);
- open_dump_file (DFI_sched2, decl);
-
- /* Do control and data sched analysis again,
- and write some more of the results to dump file. */
-
- split_all_insns (1);
-
- if (flag_sched2_use_superblocks || flag_sched2_use_traces)
- {
- schedule_ebbs (rtl_dump_file);
- /* No liveness updating code yet, but it should be easy to do.
- reg-stack recompute the liveness when needed for now. */
- count_or_remove_death_notes (NULL, 1);
- cleanup_cfg (CLEANUP_EXPENSIVE);
- }
- else
- schedule_insns (rtl_dump_file);
-
- close_dump_file (DFI_sched2, print_rtl_with_bb, insns);
- timevar_pop (TV_SCHED2);
-
- ggc_collect ();
-}
-#endif
-
-/* Register allocation pre-pass, to reduce number of moves necessary
- for two-address machines. */
-static void
-rest_of_handle_regmove (tree decl, rtx insns)
-{
- timevar_push (TV_REGMOVE);
- open_dump_file (DFI_regmove, decl);
-
- regmove_optimize (insns, max_reg_num (), rtl_dump_file);
-
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
- close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
- timevar_pop (TV_REGMOVE);
-
- ggc_collect ();
-}
-
-/* Run tracer. */
-static void
-rest_of_handle_tracer (tree decl, rtx insns)
-{
- open_dump_file (DFI_tracer, decl);
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
- tracer (0);
- cleanup_cfg (CLEANUP_EXPENSIVE);
- reg_scan (insns, max_reg_num (), 0);
- close_dump_file (DFI_tracer, print_rtl_with_bb, get_insns ());
-}
-
-/* If-conversion and CFG cleanup. */
-static void
-rest_of_handle_if_conversion (tree decl, rtx insns)
-{
- open_dump_file (DFI_ce1, decl);
- if (flag_if_conversion)
- {
- timevar_push (TV_IFCVT);
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE);
- reg_scan (insns, max_reg_num (), 0);
- if_convert (0);
- timevar_pop (TV_IFCVT);
- }
- timevar_push (TV_JUMP);
- cleanup_cfg (CLEANUP_EXPENSIVE);
- reg_scan (insns, max_reg_num (), 0);
- timevar_pop (TV_JUMP);
- close_dump_file (DFI_ce1, print_rtl_with_bb, get_insns ());
-}
-
-/* Rerun if-conversion, as combine may have simplified things enough
- to now meet sequence length restrictions. */
-static void
-rest_of_handle_if_after_combine (tree decl, rtx insns)
-{
- timevar_push (TV_IFCVT);
- open_dump_file (DFI_ce2, decl);
-
- no_new_pseudos = 0;
- if_convert (1);
- no_new_pseudos = 1;
-
- close_dump_file (DFI_ce2, print_rtl_with_bb, insns);
- timevar_pop (TV_IFCVT);
-}
-
-static void
-rest_of_handle_web (tree decl, rtx insns)
-{
- open_dump_file (DFI_web, decl);
- timevar_push (TV_WEB);
- web_main ();
- delete_trivially_dead_insns (insns, max_reg_num ());
- cleanup_cfg (CLEANUP_EXPENSIVE);
-
- timevar_pop (TV_WEB);
- close_dump_file (DFI_web, print_rtl_with_bb, insns);
- reg_scan (get_insns (), max_reg_num (), 0);
-}
-
-/* Do branch profiling and static profile estimation passes. */
-static void
-rest_of_handle_branch_prob (tree decl, rtx insns)
-{
- struct loops loops;
-
- timevar_push (TV_BRANCH_PROB);
- open_dump_file (DFI_bp, decl);
-
- if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
- branch_prob ();
-
- /* Discover and record the loop depth at the head of each basic
- block. The loop infrastructure does the real job for us. */
- flow_loops_find (&loops, LOOP_TREE);
-
- if (rtl_dump_file)
- flow_loops_dump (&loops, rtl_dump_file, NULL, 0);
-
- /* Estimate using heuristics if no profiling info is available. */
- if (flag_guess_branch_prob)
- estimate_probability (&loops);
-
- flow_loops_free (&loops);
- free_dominance_info (CDI_DOMINATORS);
- close_dump_file (DFI_bp, print_rtl_with_bb, insns);
- timevar_pop (TV_BRANCH_PROB);
-}
-
-/* Do optimizations based on expression value profiles. */
-static void
-rest_of_handle_value_profile_transformations (tree decl, rtx insns)
-{
- open_dump_file (DFI_vpt, decl);
- timevar_push (TV_VPT);
-
- if (value_profile_transformations ())
- cleanup_cfg (CLEANUP_EXPENSIVE);
-
- timevar_pop (TV_VPT);
- close_dump_file (DFI_vpt, print_rtl_with_bb, insns);
-}
-
-/* Do control and data flow analysis; write some of the results to the
- dump file. */
-static void
-rest_of_handle_cfg (tree decl, rtx insns)
-{
- open_dump_file (DFI_cfg, decl);
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
- if (optimize)
- cleanup_cfg (CLEANUP_EXPENSIVE
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
-
- /* It may make more sense to mark constant functions after dead code is
- eliminated by life_analysis, but we need to do it early, as -fprofile-arcs
- may insert code making function non-constant, but we still must consider
- it as constant, otherwise -fbranch-probabilities will not read data back.
-
- life_analysis rarely eliminates modification of external memory.
- */
- if (optimize)
- {
- /* Alias analysis depends on this information and mark_constant_function
- depends on alias analysis. */
- reg_scan (insns, max_reg_num (), 1);
- mark_constant_function ();
- }
-
- close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
-}
-
-/* Purge addressofs. */
-static void
-rest_of_handle_addressof (tree decl, rtx insns)
-{
- open_dump_file (DFI_addressof, decl);
-
- purge_addressof (insns);
- if (optimize && purge_all_dead_edges (0))
- delete_unreachable_blocks ();
- reg_scan (insns, max_reg_num (), 1);
-
- close_dump_file (DFI_addressof, print_rtl, insns);
-}
-
-/* We may have potential sibling or tail recursion sites. Select one
- (of possibly multiple) methods of performing the call. */
-static void
-rest_of_handle_sibling_calls (rtx insns)
-{
- rtx insn;
- optimize_sibling_and_tail_recursive_calls ();
-
- /* Recompute the CFG as sibling optimization clobbers it randomly. */
- free_bb_for_insn ();
- find_exception_handler_labels ();
- rebuild_jump_labels (insns);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-
- /* There is pass ordering problem - we must lower NOTE_INSN_PREDICTION
- notes before simplifying cfg and we must do lowering after sibcall
- that unhides parts of RTL chain and cleans up the CFG.
-
- Until sibcall is replaced by tree-level optimizer, lets just
- sweep away the NOTE_INSN_PREDICTION notes that leaked out. */
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION)
- delete_insn (insn);
-
- close_dump_file (DFI_sibling, print_rtl, get_insns ());
-}
-
-/* Perform jump bypassing and control flow optimizations. */
-static void
-rest_of_handle_jump_bypass (tree decl, rtx insns)
-{
- timevar_push (TV_BYPASS);
- open_dump_file (DFI_bypass, decl);
-
- cleanup_cfg (CLEANUP_EXPENSIVE);
- reg_scan (insns, max_reg_num (), 1);
-
- if (bypass_jumps (rtl_dump_file))
- {
- rebuild_jump_labels (insns);
- cleanup_cfg (CLEANUP_EXPENSIVE);
- delete_trivially_dead_insns (insns, max_reg_num ());
- }
-
- close_dump_file (DFI_bypass, print_rtl_with_bb, insns);
- timevar_pop (TV_BYPASS);
-
- ggc_collect ();
-
-#ifdef ENABLE_CHECKING
- verify_flow_info ();
-#endif
-}
-
-/* Handle inlining of functions in rest_of_compilation. Return TRUE
- if we must exit rest_of_compilation upon return. */
-static bool
-rest_of_handle_inlining (tree decl)
-{
- rtx insns;
- int inlinable = 0;
- tree parent;
- const char *lose;
-
- /* If we are reconsidering an inline function at the end of
- compilation, skip the stuff for making it inline. */
- if (cfun->rtl_inline_init)
- return 0;
- cfun->rtl_inline_init = 1;
-
- /* If this is nested inside an inlined external function, pretend
- it was only declared. Since we cannot inline such functions,
- generating code for this one is not only not necessary but will
- confuse some debugging output writers. */
- for (parent = DECL_CONTEXT (current_function_decl);
- parent != NULL_TREE;
- parent = get_containing_scope (parent))
- if (TREE_CODE (parent) == FUNCTION_DECL
- && DECL_INLINE (parent) && DECL_EXTERNAL (parent))
- {
- DECL_INITIAL (decl) = 0;
- return true;
- }
- else if (TYPE_P (parent))
- /* A function in a local class should be treated normally. */
- break;
-
- /* If requested, consider whether to make this function inline. */
- if ((DECL_INLINE (decl) && !flag_no_inline)
- || flag_inline_functions)
- {
- timevar_push (TV_INTEGRATION);
- lose = function_cannot_inline_p (decl);
- timevar_pop (TV_INTEGRATION);
- if (lose || ! optimize)
- {
- if (warn_inline && lose && DECL_INLINE (decl))
- {
- char *msg = concat ("%J", lose, NULL);
- warning (msg, decl);
- free (msg);
- }
- DECL_ABSTRACT_ORIGIN (decl) = 0;
- /* Don't really compile an extern inline function.
- If we can't make it inline, pretend
- it was only declared. */
- if (DECL_EXTERNAL (decl))
- {
- DECL_INITIAL (decl) = 0;
- return true;
- }
- }
- else
- inlinable = DECL_INLINE (decl) = 1;
- }
-
- insns = get_insns ();
-
- /* Dump the rtl code if we are dumping rtl. */
-
- if (open_dump_file (DFI_rtl, decl))
- {
- if (DECL_SAVED_INSNS (decl) && DECL_SAVED_INSNS (decl)->saved_for_inline)
- fprintf (rtl_dump_file, ";; (integrable)\n\n");
- close_dump_file (DFI_rtl, print_rtl, insns);
- }
-
- /* Convert from NOTE_INSN_EH_REGION style notes, and do other
- sorts of eh initialization. Delay this until after the
- initial rtl dump so that we can see the original nesting. */
- convert_from_eh_region_ranges ();
-
- /* If function is inline, and we don't yet know whether to
- compile it by itself, defer decision till end of compilation.
- wrapup_global_declarations will (indirectly) call
- rest_of_compilation again for those functions that need to
- be output. Also defer those functions that we are supposed
- to defer. */
-
- if (inlinable
- || (DECL_INLINE (decl)
- /* Egad. This RTL deferral test conflicts with Fortran assumptions
- for unreferenced symbols. See g77.f-torture/execute/980520-1.f.
- But removing this line from the check breaks all languages that
- use the call graph to output symbols. This hard-coded check is
- the least invasive work-around. Nested functions need to be
- deferred too. */
- && (flag_inline_functions
- || strcmp (lang_hooks.name, "GNU F77") == 0
- || (cgraph_n_nodes > 0 && cgraph_node (decl)->origin))
- && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
- && ! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
- && ! flag_keep_inline_functions)
- || DECL_EXTERNAL (decl))))
- DECL_DEFER_OUTPUT (decl) = 1;
-
- if (DECL_INLINE (decl))
- /* DWARF wants separate debugging info for abstract and
- concrete instances of all inline functions, including those
- declared inline but not inlined, and those inlined even
- though they weren't declared inline. Conveniently, that's
- what DECL_INLINE means at this point. */
- (*debug_hooks->deferred_inline_function) (decl);
-
- if (DECL_DEFER_OUTPUT (decl))
- {
- /* If -Wreturn-type, we have to do a bit of compilation. We just
- want to call cleanup the cfg to figure out whether or not we can
- fall off the end of the function; we do the minimum amount of
- work necessary to make that safe. */
- if (warn_return_type)
- {
- int saved_optimize = optimize;
-
- optimize = 0;
- rebuild_jump_labels (insns);
- find_exception_handler_labels ();
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP);
- optimize = saved_optimize;
-
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
- }
-
- set_nothrow_function_flags ();
- if (current_function_nothrow)
- /* Now we know that this can't throw; set the flag for the benefit
- of other functions later in this translation unit. */
- TREE_NOTHROW (current_function_decl) = 1;
-
- timevar_push (TV_INTEGRATION);
- save_for_inline (decl);
- timevar_pop (TV_INTEGRATION);
- DECL_SAVED_INSNS (decl)->inlinable = inlinable;
- return true;
- }
-
- /* If specified extern inline but we aren't inlining it, we are
- done. This goes for anything that gets here with DECL_EXTERNAL
- set, not just things with DECL_INLINE. */
- return (bool) DECL_EXTERNAL (decl);
-}
-
-/* Try to identify useless null pointer tests and delete them. */
-static void
-rest_of_handle_null_pointer (tree decl, rtx insns)
-{
- open_dump_file (DFI_null, decl);
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
-
- if (delete_null_pointer_checks (insns))
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
-
- close_dump_file (DFI_null, print_rtl_with_bb, insns);
-}
-
-/* Try combining insns through substitution. */
-static void
-rest_of_handle_combine (tree decl, rtx insns)
-{
- int rebuild_jump_labels_after_combine = 0;
-
- timevar_push (TV_COMBINE);
- open_dump_file (DFI_combine, decl);
-
- rebuild_jump_labels_after_combine
- = combine_instructions (insns, max_reg_num ());
-
- /* Combining insns may have turned an indirect jump into a
- direct jump. Rebuild the JUMP_LABEL fields of jumping
- instructions. */
- if (rebuild_jump_labels_after_combine)
- {
- timevar_push (TV_JUMP);
- rebuild_jump_labels (insns);
- timevar_pop (TV_JUMP);
-
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
- }
-
- close_dump_file (DFI_combine, print_rtl_with_bb, insns);
- timevar_pop (TV_COMBINE);
-
- ggc_collect ();
-}
-
-/* Perform life analysis. */
-static void
-rest_of_handle_life (tree decl, rtx insns)
-{
- open_dump_file (DFI_life, decl);
- regclass_init ();
-
-#ifdef ENABLE_CHECKING
- verify_flow_info ();
-#endif
- life_analysis (insns, rtl_dump_file, PROP_FINAL);
- if (optimize)
- cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_UPDATE_LIFE
- | CLEANUP_LOG_LINKS
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
- timevar_pop (TV_FLOW);
-
- if (warn_uninitialized)
- {
- uninitialized_vars_warning (DECL_INITIAL (decl));
- if (extra_warnings)
- setjmp_args_warning ();
- }
-
- if (optimize)
- {
- if (!flag_new_regalloc && initialize_uninitialized_subregs ())
- {
- /* Insns were inserted, and possibly pseudos created, so
- things might look a bit different. */
- insns = get_insns ();
- allocate_reg_life_data ();
- update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES);
- }
- }
-
- no_new_pseudos = 1;
-
- close_dump_file (DFI_life, print_rtl_with_bb, insns);
-
- ggc_collect ();
-}
-
-/* Perform common subexpression elimination. Nonzero value from
- `cse_main' means that jumps were simplified and some code may now
- be unreachable, so do jump optimization again. */
-static void
-rest_of_handle_cse (tree decl, rtx insns)
-{
- int tem;
-
- open_dump_file (DFI_cse, decl);
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
- timevar_push (TV_CSE);
-
- reg_scan (insns, max_reg_num (), 1);
-
- tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
- if (tem)
- rebuild_jump_labels (insns);
- if (purge_all_dead_edges (0))
- delete_unreachable_blocks ();
-
- delete_trivially_dead_insns (insns, max_reg_num ());
-
- /* If we are not running more CSE passes, then we are no longer
- expecting CSE to be run. But always rerun it in a cheap mode. */
- cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
-
- if (tem || optimize > 1)
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
- /* Try to identify useless null pointer tests and delete them. */
- if (flag_delete_null_pointer_checks)
- {
- timevar_push (TV_JUMP);
-
- if (delete_null_pointer_checks (insns))
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
- timevar_pop (TV_JUMP);
- }
-
- /* The second pass of jump optimization is likely to have
- removed a bunch more instructions. */
- renumber_insns (rtl_dump_file);
-
- timevar_pop (TV_CSE);
- close_dump_file (DFI_cse, print_rtl_with_bb, insns);
-}
-
-/* Run second CSE pass after loop optimizations. */
-static void
-rest_of_handle_cse2 (tree decl, rtx insns)
-{
- int tem;
-
- timevar_push (TV_CSE2);
- open_dump_file (DFI_cse2, decl);
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
- /* CFG is no longer maintained up-to-date. */
- tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
-
- /* Run a pass to eliminate duplicated assignments to condition code
- registers. We have to run this after bypass_jumps, because it
- makes it harder for that pass to determine whether a jump can be
- bypassed safely. */
- cse_condition_code_reg ();
-
- purge_all_dead_edges (0);
- delete_trivially_dead_insns (insns, max_reg_num ());
-
- if (tem)
- {
- timevar_push (TV_JUMP);
- rebuild_jump_labels (insns);
- cleanup_cfg (CLEANUP_EXPENSIVE);
- timevar_pop (TV_JUMP);
- }
- reg_scan (insns, max_reg_num (), 0);
- close_dump_file (DFI_cse2, print_rtl_with_bb, insns);
- ggc_collect ();
- timevar_pop (TV_CSE2);
-}
-
-/* Perform global cse. */
-static void
-rest_of_handle_gcse (tree decl, rtx insns)
-{
- int save_csb, save_cfj;
- int tem2 = 0, tem;
-
- timevar_push (TV_GCSE);
- open_dump_file (DFI_gcse, decl);
-
- tem = gcse_main (insns, rtl_dump_file);
- rebuild_jump_labels (insns);
- delete_trivially_dead_insns (insns, max_reg_num ());
-
- save_csb = flag_cse_skip_blocks;
- save_cfj = flag_cse_follow_jumps;
- flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
-
- /* Instantiate any remaining CONSTANT_P_RTX nodes. */
- if (current_function_calls_constant_p)
- purge_builtin_constant_p ();
-
- /* If -fexpensive-optimizations, re-run CSE to clean up things done
- by gcse. */
- if (flag_expensive_optimizations)
- {
- timevar_push (TV_CSE);
- reg_scan (insns, max_reg_num (), 1);
- tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
- purge_all_dead_edges (0);
- delete_trivially_dead_insns (insns, max_reg_num ());
- timevar_pop (TV_CSE);
- cse_not_expected = !flag_rerun_cse_after_loop;
- }
-
- /* If gcse or cse altered any jumps, rerun jump optimizations to clean
- things up. Then possibly re-run CSE again. */
- while (tem || tem2)
- {
- tem = tem2 = 0;
- timevar_push (TV_JUMP);
- rebuild_jump_labels (insns);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
- timevar_pop (TV_JUMP);
-
- if (flag_expensive_optimizations)
- {
- timevar_push (TV_CSE);
- reg_scan (insns, max_reg_num (), 1);
- tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
- purge_all_dead_edges (0);
- delete_trivially_dead_insns (insns, max_reg_num ());
- timevar_pop (TV_CSE);
- }
- }
-
- close_dump_file (DFI_gcse, print_rtl_with_bb, insns);
- timevar_pop (TV_GCSE);
-
- ggc_collect ();
- flag_cse_skip_blocks = save_csb;
- flag_cse_follow_jumps = save_cfj;
-#ifdef ENABLE_CHECKING
- verify_flow_info ();
-#endif
-}
-
-/* Move constant computations out of loops. */
-static void
-rest_of_handle_loop_optimize (tree decl, rtx insns)
-{
- int do_unroll, do_prefetch;
-
- timevar_push (TV_LOOP);
- delete_dead_jumptables ();
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
- open_dump_file (DFI_loop, decl);
-
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
-
- if (flag_unroll_loops)
- do_unroll = LOOP_AUTO_UNROLL; /* Having two unrollers is useless. */
- else
- do_unroll = flag_old_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL;
- do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0;
-
- if (flag_rerun_loop_opt)
- {
- cleanup_barriers ();
-
- /* We only want to perform unrolling once. */
- loop_optimize (insns, rtl_dump_file, do_unroll);
- do_unroll = 0;
-
- /* The first call to loop_optimize makes some instructions
- trivially dead. We delete those instructions now in the
- hope that doing so will make the heuristics in loop work
- better and possibly speed up compilation. */
- delete_trivially_dead_insns (insns, max_reg_num ());
-
- /* The regscan pass is currently necessary as the alias
- analysis code depends on this information. */
- reg_scan (insns, max_reg_num (), 1);
- }
- cleanup_barriers ();
- loop_optimize (insns, rtl_dump_file, do_unroll | LOOP_BCT | do_prefetch);
-
- /* Loop can create trivially dead instructions. */
- delete_trivially_dead_insns (insns, max_reg_num ());
- close_dump_file (DFI_loop, print_rtl, insns);
- timevar_pop (TV_LOOP);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-
- ggc_collect ();
-}
-
-/* Perform loop optimizations. It might be better to do them a bit
- sooner, but we want the profile feedback to work more
- efficiently. */
-static void
-rest_of_handle_loop2 (tree decl, rtx insns)
-{
- struct loops *loops;
- timevar_push (TV_LOOP);
- open_dump_file (DFI_loop2, decl);
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
-
- loops = loop_optimizer_init (rtl_dump_file);
-
- if (loops)
- {
- /* The optimizations: */
- if (flag_unswitch_loops)
- unswitch_loops (loops);
-
- if (flag_peel_loops || flag_unroll_loops)
- unroll_and_peel_loops (loops,
- (flag_peel_loops ? UAP_PEEL : 0) |
- (flag_unroll_loops ? UAP_UNROLL : 0) |
- (flag_unroll_all_loops ? UAP_UNROLL_ALL : 0));
-
- loop_optimizer_finalize (loops, rtl_dump_file);
- }
-
- cleanup_cfg (CLEANUP_EXPENSIVE);
- delete_trivially_dead_insns (insns, max_reg_num ());
- reg_scan (insns, max_reg_num (), 0);
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
- close_dump_file (DFI_loop2, print_rtl_with_bb, get_insns ());
- timevar_pop (TV_LOOP);
- ggc_collect ();
-}
-
-/* This is called from finish_function (within langhooks.parse_file)
- after each top-level definition is parsed.
- It is supposed to compile that function or variable
- and output the assembler code for it.
- After we return, the tree storage is freed. */
-
-void
-rest_of_compilation (tree decl)
-{
- rtx insns;
-
- timevar_push (TV_REST_OF_COMPILATION);
-
- /* Register rtl specific functions for cfg. */
- rtl_register_cfg_hooks ();
-
- /* Now that we're out of the frontend, we shouldn't have any more
- CONCATs anywhere. */
- generating_concat_p = 0;
-
- /* When processing delayed functions, prepare_function_start() won't
- have been run to re-initialize it. */
- cse_not_expected = ! optimize;
-
- /* First, make sure that NOTE_BLOCK is set correctly for each
- NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note. */
- if (!cfun->x_whole_function_mode_p)
- identify_blocks ();
-
- /* In function-at-a-time mode, we do not attempt to keep the BLOCK
- tree in sensible shape. So, we just recalculate it here. */
- if (cfun->x_whole_function_mode_p)
- reorder_blocks ();
-
- init_flow ();
-
- if (rest_of_handle_inlining (decl))
- goto exit_rest_of_compilation;
-
- /* If we're emitting a nested function, make sure its parent gets
- emitted as well. Doing otherwise confuses debug info. */
- {
- tree parent;
- for (parent = DECL_CONTEXT (current_function_decl);
- parent != NULL_TREE;
- parent = get_containing_scope (parent))
- if (TREE_CODE (parent) == FUNCTION_DECL)
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1;
- }
-
- /* We are now committed to emitting code for this function. Do any
- preparation, such as emitting abstract debug info for the inline
- before it gets mangled by optimization. */
- if (cgraph_function_possibly_inlined_p (decl))
- (*debug_hooks->outlining_inline_function) (decl);
-
- /* Remove any notes we don't need. That will make iterating
- over the instruction sequence faster, and allow the garbage
- collector to reclaim the memory used by the notes. */
- remove_unnecessary_notes ();
- reorder_blocks ();
-
- ggc_collect ();
-
- /* Initialize some variables used by the optimizers. */
- init_function_for_compilation ();
-
- if (! DECL_DEFER_OUTPUT (decl))
- TREE_ASM_WRITTEN (decl) = 1;
-
- /* Now that integrate will no longer see our rtl, we need not
- distinguish between the return value of this function and the
- return value of called functions. Also, we can remove all SETs
- of subregs of hard registers; they are only here because of
- integrate. Also, we can now initialize pseudos intended to
- carry magic hard reg data throughout the function. */
- rtx_equal_function_value_matters = 0;
- purge_hard_subreg_sets (get_insns ());
-
- /* Early return if there were errors. We can run afoul of our
- consistency checks, and there's not really much point in fixing them.
- Don't return yet if -Wreturn-type; we need to do cleanup_cfg. */
- if (((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
- || errorcount || sorrycount)
- goto exit_rest_of_compilation;
-
- timevar_push (TV_JUMP);
- open_dump_file (DFI_sibling, decl);
- insns = get_insns ();
- rebuild_jump_labels (insns);
- find_exception_handler_labels ();
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-
- delete_unreachable_blocks ();
-
- /* Turn NOTE_INSN_PREDICTIONs into branch predictions. */
- if (flag_guess_branch_prob)
- {
- timevar_push (TV_BRANCH_PROB);
- note_prediction_to_br_prob ();
- timevar_pop (TV_BRANCH_PROB);
- }
-
- if (flag_optimize_sibling_calls)
- rest_of_handle_sibling_calls (insns);
-
- /* We have to issue these warnings now already, because CFG cleanups
- further down may destroy the required information. However, this
- must be done after the sibcall optimization pass because the barrier
- emitted for noreturn calls that are candidate for the optimization
- is folded into the CALL_PLACEHOLDER until after this pass, so the
- CFG is inaccurate. */
- check_function_return_warnings ();
-
- timevar_pop (TV_JUMP);
-
- insn_locators_initialize ();
- /* Complete generation of exception handling code. */
- if (doing_eh (0))
- {
- timevar_push (TV_JUMP);
- open_dump_file (DFI_eh, decl);
-
- finish_eh_generation ();
-
- close_dump_file (DFI_eh, print_rtl, get_insns ());
- timevar_pop (TV_JUMP);
- }
-
- /* Delay emitting hard_reg_initial_value sets until after EH landing pad
- generation, which might create new sets. */
- emit_initial_value_sets ();
-
-#ifdef FINALIZE_PIC
- /* If we are doing position-independent code generation, now
- is the time to output special prologues and epilogues.
- We do not want to do this earlier, because it just clutters
- up inline functions with meaningless insns. */
- if (flag_pic)
- FINALIZE_PIC;
-#endif
-
- insns = get_insns ();
-
- /* Copy any shared structure that should not be shared. */
- unshare_all_rtl (current_function_decl, insns);
-
-#ifdef SETJMP_VIA_SAVE_AREA
- /* This must be performed before virtual register instantiation.
- Please be aware the everything in the compiler that can look
- at the RTL up to this point must understand that REG_SAVE_AREA
- is just like a use of the REG contained inside. */
- if (current_function_calls_alloca)
- optimize_save_area_alloca (insns);
-#endif
-
- /* Instantiate all virtual registers. */
- instantiate_virtual_regs (current_function_decl, insns);
-
- open_dump_file (DFI_jump, decl);
-
- /* Always do one jump optimization pass to ensure that JUMP_LABEL fields
- are initialized and to compute whether control can drop off the end
- of the function. */
-
- timevar_push (TV_JUMP);
- /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this
- before jump optimization switches branch directions. */
- if (flag_guess_branch_prob)
- expected_value_to_br_prob ();
-
- reg_scan (insns, max_reg_num (), 0);
- rebuild_jump_labels (insns);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- delete_trivially_dead_insns (insns, max_reg_num ());
- if (rtl_dump_file)
- dump_flow_info (rtl_dump_file);
- cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
-
- if (optimize)
- {
- free_bb_for_insn ();
- copy_loop_headers (insns);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- }
- purge_line_number_notes (insns);
-
- timevar_pop (TV_JUMP);
- close_dump_file (DFI_jump, print_rtl, insns);
-
- /* Now is when we stop if -fsyntax-only and -Wreturn-type. */
- if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
- goto exit_rest_of_compilation;
-
- timevar_push (TV_JUMP);
-
- if (optimize)
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
-
- if (flag_delete_null_pointer_checks)
- rest_of_handle_null_pointer (decl, insns);
-
- /* Jump optimization, and the removal of NULL pointer checks, may
- have reduced the number of instructions substantially. CSE, and
- future passes, allocate arrays whose dimensions involve the
- maximum instruction UID, so if we can reduce the maximum UID
- we'll save big on memory. */
- renumber_insns (rtl_dump_file);
- timevar_pop (TV_JUMP);
-
- close_dump_file (DFI_jump, print_rtl_with_bb, insns);
-
- ggc_collect ();
-
- if (optimize > 0)
- rest_of_handle_cse (decl, insns);
-
- rest_of_handle_addressof (decl, insns);
-
- ggc_collect ();
-
- if (optimize > 0)
- {
- if (flag_gcse)
- rest_of_handle_gcse (decl, insns);
-
- if (flag_loop_optimize)
- rest_of_handle_loop_optimize (decl, insns);
-
- if (flag_gcse)
- rest_of_handle_jump_bypass (decl, insns);
- }
-
- timevar_push (TV_FLOW);
-
- rest_of_handle_cfg (decl, insns);
-
- if (optimize > 0
- || profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
- {
- rest_of_handle_branch_prob (decl, insns);
-
- if (flag_branch_probabilities
- && flag_profile_values
- && flag_value_profile_transformations)
- rest_of_handle_value_profile_transformations (decl, insns);
-
- /* Remove the death notes created for vpt. */
- if (flag_profile_values)
- count_or_remove_death_notes (NULL, 1);
- }
-
- if (optimize > 0)
- rest_of_handle_if_conversion (decl, insns);
-
- if (flag_tracer)
- rest_of_handle_tracer (decl, insns);
-
- if (optimize > 0
- && (flag_unswitch_loops
- || flag_peel_loops
- || flag_unroll_loops))
- rest_of_handle_loop2 (decl, insns);
-
- if (flag_web)
- rest_of_handle_web (decl, insns);
-
- if (flag_rerun_cse_after_loop)
- rest_of_handle_cse2 (decl, insns);
-
- cse_not_expected = 1;
-
- rest_of_handle_life (decl, insns);
-
- if (optimize > 0)
- rest_of_handle_combine (decl, insns);
-
- if (flag_if_conversion)
- rest_of_handle_if_after_combine (decl, insns);
-
- if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
- rest_of_handle_regmove (decl, insns);
-
- /* Do unconditional splitting before register allocation to allow machine
- description to add extra information not needed previously. */
- split_all_insns (1);
-
-#ifdef OPTIMIZE_MODE_SWITCHING
- timevar_push (TV_MODE_SWITCH);
-
- no_new_pseudos = 0;
- optimize_mode_switching (NULL);
- no_new_pseudos = 1;
-
- timevar_pop (TV_MODE_SWITCH);
-#endif
-
- /* Any of the several passes since flow1 will have munged register
- lifetime data a bit. We need it to be up to date for scheduling
- (see handling of reg_known_equiv in init_alias_analysis). */
- recompute_reg_usage (insns, !optimize_size);
-
-#ifdef INSN_SCHEDULING
- rest_of_handle_sched (decl, insns);
-#endif
-
- /* Determine if the current function is a leaf before running reload
- since this can impact optimizations done by the prologue and
- epilogue thus changing register elimination offsets. */
- current_function_is_leaf = leaf_function_p ();
-
- timevar_push (TV_LOCAL_ALLOC);
- open_dump_file (DFI_lreg, decl);
-
- if (flag_new_regalloc)
- {
- if (rest_of_handle_new_regalloc (decl, insns))
- goto exit_rest_of_compilation;
- }
- else
- {
- if (rest_of_handle_old_regalloc (decl, insns))
- goto exit_rest_of_compilation;
- }
-
- ggc_collect ();
-
- open_dump_file (DFI_postreload, decl);
-
- /* Do a very simple CSE pass over just the hard registers. */
- if (optimize > 0)
- {
- timevar_push (TV_RELOAD_CSE_REGS);
- reload_cse_regs (insns);
- /* reload_cse_regs can eliminate potentially-trapping MEMs.
- Remove any EH edges associated with them. */
- if (flag_non_call_exceptions)
- purge_all_dead_edges (0);
- timevar_pop (TV_RELOAD_CSE_REGS);
- }
-
- close_dump_file (DFI_postreload, print_rtl_with_bb, insns);
-
- /* Re-create the death notes which were deleted during reload. */
- timevar_push (TV_FLOW2);
- open_dump_file (DFI_flow2, decl);
-
-#ifdef ENABLE_CHECKING
- verify_flow_info ();
-#endif
-
- /* If optimizing, then go ahead and split insns now. */
-#ifndef STACK_REGS
- if (optimize > 0)
-#endif
- split_all_insns (0);
-
- if (flag_branch_target_load_optimize)
- {
- open_dump_file (DFI_branch_target_load, decl);
-
- branch_target_load_optimize (insns, false);
-
- close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns);
-
- ggc_collect ();
- }
-
- if (optimize)
- cleanup_cfg (CLEANUP_EXPENSIVE);
-
- /* On some machines, the prologue and epilogue code, or parts thereof,
- can be represented as RTL. Doing so lets us schedule insns between
- it and the rest of the code and also allows delayed branch
- scheduling to operate in the epilogue. */
- thread_prologue_and_epilogue_insns (insns);
- epilogue_completed = 1;
-
- if (optimize)
- {
- life_analysis (insns, rtl_dump_file, PROP_POSTRELOAD);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE
- | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
-
- /* This is kind of a heuristic. We need to run combine_stack_adjustments
- even for machines with possibly nonzero RETURN_POPS_ARGS
- and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having
- push instructions will have popping returns. */
-#ifndef PUSH_ROUNDING
- if (!ACCUMULATE_OUTGOING_ARGS)
-#endif
- combine_stack_adjustments ();
-
- ggc_collect ();
- }
-
- flow2_completed = 1;
-
- close_dump_file (DFI_flow2, print_rtl_with_bb, insns);
- timevar_pop (TV_FLOW2);
-
-#ifdef HAVE_peephole2
- if (optimize > 0 && flag_peephole2)
- {
- timevar_push (TV_PEEPHOLE2);
- open_dump_file (DFI_peephole2, decl);
-
- peephole2_optimize (rtl_dump_file);
-
- close_dump_file (DFI_peephole2, print_rtl_with_bb, insns);
- timevar_pop (TV_PEEPHOLE2);
- }
-#endif
-
- open_dump_file (DFI_ce3, decl);
- if (optimize)
- /* Last attempt to optimize CFG, as scheduling, peepholing and insn
- splitting possibly introduced more crossjumping opportunities. */
- cleanup_cfg (CLEANUP_EXPENSIVE
- | CLEANUP_UPDATE_LIFE
- | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
- if (flag_if_conversion2)
- {
- timevar_push (TV_IFCVT2);
-
- if_convert (1);
-
- timevar_pop (TV_IFCVT2);
- }
- close_dump_file (DFI_ce3, print_rtl_with_bb, insns);
-
- if (optimize > 0)
- {
- if (flag_rename_registers || flag_cprop_registers)
- rest_of_handle_regrename (decl, insns);
-
- rest_of_handle_reorder_blocks (decl, insns);
- }
-
- if (flag_branch_target_load_optimize2)
- {
- /* Leave this a warning for now so that it is possible to experiment
- with running this pass twice. In 3.6, we should either make this
- an error, or use separate dump files. */
- if (flag_branch_target_load_optimize)
- warning ("branch target register load optimization is not intended "
- "to be run twice");
-
- open_dump_file (DFI_branch_target_load, decl);
-
- branch_target_load_optimize (insns, true);
-
- close_dump_file (DFI_branch_target_load, print_rtl_with_bb, insns);
-
- ggc_collect ();
- }
-
-#ifdef INSN_SCHEDULING
- if (optimize > 0 && flag_schedule_insns_after_reload)
- rest_of_handle_sched2 (decl, insns);
-#endif
-
-#ifdef LEAF_REGISTERS
- current_function_uses_only_leaf_regs
- = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
-#endif
-
-#ifdef STACK_REGS
- rest_of_handle_stack_regs (decl, insns);
-#endif
-
- compute_alignments ();
-
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
-
- if (targetm.machine_dependent_reorg != 0)
- rest_of_handle_machine_reorg (decl, insns);
-
- purge_line_number_notes (insns);
- cleanup_barriers ();
-
-#ifdef DELAY_SLOTS
- if (optimize > 0 && flag_delayed_branch)
- rest_of_handle_delay_slots (decl, insns);
-#endif
-
-#if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
- timevar_push (TV_SHORTEN_BRANCH);
- split_all_insns_noflow ();
- timevar_pop (TV_SHORTEN_BRANCH);
-#endif
-
- convert_to_eh_region_ranges ();
-
- /* Shorten branches. */
- timevar_push (TV_SHORTEN_BRANCH);
- shorten_branches (get_insns ());
- timevar_pop (TV_SHORTEN_BRANCH);
-
- set_nothrow_function_flags ();
- if (current_function_nothrow)
- /* Now we know that this can't throw; set the flag for the benefit
- of other functions later in this translation unit. */
- TREE_NOTHROW (current_function_decl) = 1;
-
- rest_of_handle_final (decl, insns);
-
- /* Write DBX symbols if requested. */
-
- /* Note that for those inline functions where we don't initially
- know for certain that we will be generating an out-of-line copy,
- the first invocation of this routine (rest_of_compilation) will
- skip over this code by doing a `goto exit_rest_of_compilation;'.
- Later on, wrapup_global_declarations will (indirectly) call
- rest_of_compilation again for those inline functions that need
- to have out-of-line copies generated. During that call, we
- *will* be routed past here. */
-
- timevar_push (TV_SYMOUT);
- (*debug_hooks->function_decl) (decl);
- timevar_pop (TV_SYMOUT);
-
- exit_rest_of_compilation:
-
- coverage_end_function ();
-
- /* In case the function was not output,
- don't leave any temporary anonymous types
- queued up for sdb output. */
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG)
- sdbout_types (NULL_TREE);
-#endif
-
- reload_completed = 0;
- epilogue_completed = 0;
- flow2_completed = 0;
- no_new_pseudos = 0;
-
- timevar_push (TV_FINAL);
-
- /* Clear out the insn_length contents now that they are no
- longer valid. */
- init_insn_lengths ();
-
- /* Show no temporary slots allocated. */
- init_temp_slots ();
-
- free_basic_block_vars (0);
- free_bb_for_insn ();
-
- timevar_pop (TV_FINAL);
-
- if ((*targetm.binds_local_p) (current_function_decl))
- {
- int pref = cfun->preferred_stack_boundary;
- if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary)
- pref = cfun->stack_alignment_needed;
- cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary
- = pref;
- }
-
- /* Make sure volatile mem refs aren't considered valid operands for
- arithmetic insns. We must call this here if this is a nested inline
- function, since the above code leaves us in the init_recog state
- (from final.c), and the function context push/pop code does not
- save/restore volatile_ok.
-
- ??? Maybe it isn't necessary for expand_start_function to call this
- anymore if we do it here? */
-
- init_recog_no_volatile ();
-
- /* We're done with this function. Free up memory if we can. */
- free_after_parsing (cfun);
- if (! DECL_DEFER_OUTPUT (decl))
- {
- free_after_compilation (cfun);
- DECL_SAVED_INSNS (decl) = 0;
- }
- cfun = 0;
-
- ggc_collect ();
-
- timevar_pop (TV_REST_OF_COMPILATION);
-}
-
-/* Display help for target options. */
-void
-display_target_options (void)
-{
- int undoc, i;
- static bool displayed = false;
-
- /* Avoid double printing for --help --target-help. */
- if (displayed)
- return;
-
- displayed = true;
-
- if (ARRAY_SIZE (target_switches) > 1
-#ifdef TARGET_OPTIONS
- || ARRAY_SIZE (target_options) > 1
-#endif
- )
- {
- int doc = 0;
-
- undoc = 0;
-
- printf (_("\nTarget specific options:\n"));
-
- for (i = ARRAY_SIZE (target_switches); i--;)
- {
- const char *option = target_switches[i].name;
- const char *description = target_switches[i].description;
-
- if (option == NULL || *option == 0)
- continue;
- else if (description == NULL)
- {
- undoc = 1;
-
- if (extra_warnings)
- printf (_(" -m%-23s [undocumented]\n"), option);
- }
- else if (*description != 0)
- doc += printf (" -m%-23s %s\n", option, _(description));
- }
-
-#ifdef TARGET_OPTIONS
- for (i = ARRAY_SIZE (target_options); i--;)
- {
- const char *option = target_options[i].prefix;
- const char *description = target_options[i].description;
-
- if (option == NULL || *option == 0)
- continue;
- else if (description == NULL)
- {
- undoc = 1;
-
- if (extra_warnings)
- printf (_(" -m%-23s [undocumented]\n"), option);
- }
- else if (*description != 0)
- doc += printf (" -m%-23s %s\n", option, _(description));
- }
-#endif
- if (undoc)
- {
- if (doc)
- printf (_("\nThere are undocumented target specific options as well.\n"));
- else
- printf (_(" They exist, but they are not documented.\n"));
- }
- }
+ /* This must be at the end. Some target ports emit end of file directives
+ into the assembly file here, and hence we can not output anything to the
+ assembly file after this point. */
+ targetm.asm_out.file_end ();
}
/* Parse a -d... command line switch. */
@@ -3773,15 +1105,11 @@ display_target_options (void)
void
decode_d_option (const char *arg)
{
- int i, c, matched;
+ int c;
while (*arg)
switch (c = *arg++)
{
- case 'a':
- for (i = 0; i < (int) DFI_MAX; ++i)
- dump_file[i].enabled = 1;
- break;
case 'A':
flag_debug_asm = 1;
break;
@@ -3808,17 +1136,10 @@ decode_d_option (const char *arg)
setup_core_dumping();
break;
+ case 'a':
default:
- matched = 0;
- for (i = 0; i < (int) DFI_MAX; ++i)
- if (c == dump_file[i].debug_switch)
- {
- dump_file[i].enabled = 1;
- matched = 1;
- }
-
- if (! matched)
- warning ("unrecognized gcc debugging option: %c", c);
+ if (!enable_rtl_dump_file (c))
+ warning (0, "unrecognized gcc debugging option: %c", c);
break;
}
}
@@ -3826,63 +1147,9 @@ decode_d_option (const char *arg)
/* Indexed by enum debug_info_type. */
const char *const debug_type_names[] =
{
- "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff", "vms"
+ "none", "stabs", "coff", "dwarf-2", "xcoff", "vms"
};
-/* Decode -m switches. */
-/* Decode the switch -mNAME. */
-
-void
-set_target_switch (const char *name)
-{
- size_t j;
- int valid_target_option = 0;
-
- for (j = 0; j < ARRAY_SIZE (target_switches); j++)
- if (!strcmp (target_switches[j].name, name))
- {
- if (target_switches[j].value < 0)
- target_flags &= ~-target_switches[j].value;
- else
- target_flags |= target_switches[j].value;
- if (name[0] != 0)
- {
- if (target_switches[j].value < 0)
- target_flags_explicit |= -target_switches[j].value;
- else
- target_flags_explicit |= target_switches[j].value;
- }
- valid_target_option = 1;
- }
-
-#ifdef TARGET_OPTIONS
- if (!valid_target_option)
- for (j = 0; j < ARRAY_SIZE (target_options); j++)
- {
- int len = strlen (target_options[j].prefix);
- if (target_options[j].value)
- {
- if (!strcmp (target_options[j].prefix, name))
- {
- *target_options[j].variable = target_options[j].value;
- valid_target_option = 1;
- }
- }
- else
- {
- if (!strncmp (target_options[j].prefix, name, len))
- {
- *target_options[j].variable = name + len;
- valid_target_option = 1;
- }
- }
- }
-#endif
-
- if (!valid_target_option)
- error ("invalid option `%s'", name);
-}
-
/* Print version information to FILE.
Each line begins with INDENT (for the case where FILE is the
assembler output file). */
@@ -3890,19 +1157,25 @@ set_target_switch (const char *name)
void
print_version (FILE *file, const char *indent)
{
-#ifndef __VERSION__
-#define __VERSION__ "[?]"
-#endif
- fnotice (file,
+ static const char fmt1[] =
#ifdef __GNUC__
- "%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n"
+ N_("%s%s%s version %s (%s)\n%s\tcompiled by GNU C version %s.\n")
#else
- "%s%s%s version %s (%s) compiled by CC.\n"
+ N_("%s%s%s version %s (%s) compiled by CC.\n")
#endif
- , indent, *indent != 0 ? " " : "",
+ ;
+ static const char fmt2[] =
+ N_("%s%sGGC heuristics: --param ggc-min-expand=%d --param ggc-min-heapsize=%d\n");
+#ifndef __VERSION__
+#define __VERSION__ "[?]"
+#endif
+ fprintf (file,
+ file == stderr ? _(fmt1) : fmt1,
+ indent, *indent != 0 ? " " : "",
lang_hooks.name, version_string, TARGET_NAME,
indent, __VERSION__);
- fnotice (file, "%s%sGGC heuristics: --param ggc-min-expand=%d --param ggc-min-heapsize=%d\n",
+ fprintf (file,
+ file == stderr ? _(fmt2) : fmt2,
indent, *indent != 0 ? " " : "",
PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
}
@@ -3985,33 +1258,11 @@ print_switch_values (FILE *file, int pos, int max,
pos = print_single_switch (file, 0, max, indent, *indent ? " " : "", term,
_("options enabled: "), "");
- for (j = 0; j < ARRAY_SIZE (f_options); j++)
- if (*f_options[j].variable == f_options[j].on_value)
+ for (j = 0; j < cl_options_count; j++)
+ if ((cl_options[j].flags & CL_REPORT)
+ && option_enabled (j) > 0)
pos = print_single_switch (file, pos, max, indent, sep, term,
- "-f", f_options[j].string);
-
- /* Print target specific options. */
-
- for (j = 0; j < ARRAY_SIZE (target_switches); j++)
- if (target_switches[j].name[0] != '\0'
- && target_switches[j].value > 0
- && ((target_switches[j].value & target_flags)
- == target_switches[j].value))
- {
- pos = print_single_switch (file, pos, max, indent, sep, term,
- "-m", target_switches[j].name);
- }
-
-#ifdef TARGET_OPTIONS
- for (j = 0; j < ARRAY_SIZE (target_options); j++)
- if (*target_options[j].variable != NULL)
- {
- char prefix[256];
- sprintf (prefix, "-m%s", target_options[j].prefix);
- pos = print_single_switch (file, pos, max, indent, sep, term,
- prefix, *target_options[j].variable);
- }
-#endif
+ "", cl_options[j].opt_text);
fprintf (file, "%s", term);
}
@@ -4030,7 +1281,7 @@ init_asm_output (const char *name)
if (asm_file_name == 0)
{
int len = strlen (dump_base_name);
- char *dumpname = xmalloc (len + 6);
+ char *dumpname = XNEWVEC (char, len + 6);
memcpy (dumpname, dump_base_name, len + 1);
strip_off_ending (dumpname, len);
strcat (dumpname, ".s");
@@ -4039,16 +1290,11 @@ init_asm_output (const char *name)
if (!strcmp (asm_file_name, "-"))
asm_out_file = stdout;
else
- asm_out_file = fopen (asm_file_name, "w+");
+ asm_out_file = fopen (asm_file_name, "w+b");
if (asm_out_file == 0)
- fatal_error ("can't open %s for writing: %m", asm_file_name);
+ fatal_error ("can%'t open %s for writing: %m", asm_file_name);
}
-#ifdef IO_BUFFER_SIZE
- setvbuf (asm_out_file, xmalloc (IO_BUFFER_SIZE),
- _IOFBF, IO_BUFFER_SIZE);
-#endif
-
if (!flag_syntax_only)
{
targetm.asm_out.file_start ();
@@ -4068,6 +1314,21 @@ init_asm_output (const char *name)
}
}
+/* Return true if the state of option OPTION should be stored in PCH files
+ and checked by default_pch_valid_p. Store the option's current state
+ in STATE if so. */
+
+static inline bool
+option_affects_pch_p (int option, struct cl_option_state *state)
+{
+ if ((cl_options[option].flags & CL_TARGET) == 0)
+ return false;
+ if (cl_options[option].flag_var == &target_flags)
+ if (targetm.check_pch_target_flags)
+ return false;
+ return get_option_state (option, state);
+}
+
/* Default version of get_pch_validity.
By default, every flag difference is fatal; that will be mostly right for
most targets, but completely right for very few. */
@@ -4075,51 +1336,58 @@ init_asm_output (const char *name)
void *
default_get_pch_validity (size_t *len)
{
-#ifdef TARGET_OPTIONS
+ struct cl_option_state state;
size_t i;
-#endif
char *result, *r;
- *len = sizeof (target_flags) + 2;
-#ifdef TARGET_OPTIONS
- for (i = 0; i < ARRAY_SIZE (target_options); i++)
- {
- *len += 1;
- if (*target_options[i].variable)
- *len += strlen (*target_options[i].variable);
- }
-#endif
+ *len = 2;
+ if (targetm.check_pch_target_flags)
+ *len += sizeof (target_flags);
+ for (i = 0; i < cl_options_count; i++)
+ if (option_affects_pch_p (i, &state))
+ *len += state.size;
- result = r = xmalloc (*len);
+ result = r = XNEWVEC (char, *len);
r[0] = flag_pic;
r[1] = flag_pie;
r += 2;
- memcpy (r, &target_flags, sizeof (target_flags));
- r += sizeof (target_flags);
-
-#ifdef TARGET_OPTIONS
- for (i = 0; i < ARRAY_SIZE (target_options); i++)
+ if (targetm.check_pch_target_flags)
{
- const char *str = *target_options[i].variable;
- size_t l;
- if (! str)
- str = "";
- l = strlen (str) + 1;
- memcpy (r, str, l);
- r += l;
+ memcpy (r, &target_flags, sizeof (target_flags));
+ r += sizeof (target_flags);
}
-#endif
+
+ for (i = 0; i < cl_options_count; i++)
+ if (option_affects_pch_p (i, &state))
+ {
+ memcpy (r, state.data, state.size);
+ r += state.size;
+ }
return result;
}
+/* Return a message which says that a PCH file was created with a different
+ setting of OPTION. */
+
+static const char *
+pch_option_mismatch (const char *option)
+{
+ char *r;
+
+ asprintf (&r, _("created and used with differing settings of '%s'"), option);
+ if (r == NULL)
+ return _("out of memory");
+ return r;
+}
+
/* Default version of pch_valid_p. */
const char *
default_pch_valid_p (const void *data_p, size_t len)
{
+ struct cl_option_state state;
const char *data = (const char *)data_p;
- const char *flag_that_differs = NULL;
size_t i;
/* -fpic and -fpie also usually make a PCH invalid. */
@@ -4130,82 +1398,73 @@ default_pch_valid_p (const void *data_p, size_t len)
data += 2;
/* Check target_flags. */
- if (memcmp (data, &target_flags, sizeof (target_flags)) != 0)
+ if (targetm.check_pch_target_flags)
{
- for (i = 0; i < ARRAY_SIZE (target_switches); i++)
- {
- int bits;
- int tf;
-
- memcpy (&tf, data, sizeof (target_flags));
-
- bits = target_switches[i].value;
- if (bits < 0)
- bits = -bits;
- if ((target_flags & bits) != (tf & bits))
- {
- flag_that_differs = target_switches[i].name;
- goto make_message;
- }
- }
- abort ();
- }
- data += sizeof (target_flags);
- len -= sizeof (target_flags);
+ int tf;
+ const char *r;
- /* Check string options. */
-#ifdef TARGET_OPTIONS
- for (i = 0; i < ARRAY_SIZE (target_options); i++)
- {
- const char *str = *target_options[i].variable;
- size_t l;
- if (! str)
- str = "";
- l = strlen (str) + 1;
- if (len < l || memcmp (data, str, l) != 0)
- {
- flag_that_differs = target_options[i].prefix;
- goto make_message;
- }
- data += l;
- len -= l;
+ memcpy (&tf, data, sizeof (target_flags));
+ data += sizeof (target_flags);
+ len -= sizeof (target_flags);
+ r = targetm.check_pch_target_flags (tf);
+ if (r != NULL)
+ return r;
}
-#endif
- return NULL;
+ for (i = 0; i < cl_options_count; i++)
+ if (option_affects_pch_p (i, &state))
+ {
+ if (memcmp (data, state.data, state.size) != 0)
+ return pch_option_mismatch (cl_options[i].opt_text);
+ data += state.size;
+ len -= state.size;
+ }
- make_message:
- {
- char *r;
- asprintf (&r, _("created and used with differing settings of `-m%s'"),
- flag_that_differs);
- if (r == NULL)
- return _("out of memory");
- return r;
- }
+ return NULL;
}
/* Default tree printer. Handles declarations only. */
static bool
-default_tree_printer (pretty_printer * pp, text_info *text)
+default_tree_printer (pretty_printer * pp, text_info *text, const char *spec,
+ int precision, bool wide, bool set_locus, bool hash)
{
- switch (*text->format_spec)
+ tree t;
+
+ /* FUTURE: %+x should set the locus. */
+ if (precision != 0 || wide || hash)
+ return false;
+
+ switch (*spec)
{
case 'D':
+ t = va_arg (*text->args_ptr, tree);
+ if (DECL_DEBUG_EXPR_IS_FROM (t) && DECL_DEBUG_EXPR (t))
+ t = DECL_DEBUG_EXPR (t);
+ break;
+
case 'F':
case 'T':
- {
- tree t = va_arg (*text->args_ptr, tree);
- const char *n = DECL_NAME (t)
- ? (*lang_hooks.decl_printable_name) (t, 2)
- : "<anonymous>";
- pp_string (pp, n);
- }
- return true;
+ t = va_arg (*text->args_ptr, tree);
+ break;
default:
return false;
}
+
+ if (set_locus && text->locus)
+ *text->locus = DECL_SOURCE_LOCATION (t);
+
+ if (DECL_P (t))
+ {
+ const char *n = DECL_NAME (t)
+ ? lang_hooks.decl_printable_name (t, 2)
+ : "<anonymous>";
+ pp_string (pp, n);
+ }
+ else
+ dump_generic_node (pp, t, 0, 0, 0);
+
+ return true;
}
/* Initialization of the front end environment, before command line
@@ -4225,6 +1484,9 @@ general_init (const char *argv0)
hex_init ();
+ /* Unlock the stdio streams. */
+ unlock_std_streams ();
+
gcc_init_libintl ();
/* Initialize the diagnostics reporting machinery, so option parsing
@@ -4261,6 +1523,7 @@ general_init (const char *argv0)
table. */
init_ggc ();
init_stringpool ();
+ linemap_init (&line_table);
init_ttree ();
/* Initialize register usage now so switches may override. */
@@ -4271,6 +1534,21 @@ general_init (const char *argv0)
/* This must be done after add_params but before argument processing. */
init_ggc_heuristics();
+ init_optimization_passes ();
+}
+
+/* Return true if the current target supports -fsection-anchors. */
+
+static bool
+target_supports_section_anchors_p (void)
+{
+ if (targetm.min_anchor_offset == 0 && targetm.max_anchor_offset == 0)
+ return false;
+
+ if (targetm.asm_out.output_anchor == NULL)
+ return false;
+
+ return true;
}
/* Process the options that have been parsed. */
@@ -4285,14 +1563,26 @@ process_options (void)
initialization based on the command line options. This hook also
sets the original filename if appropriate (e.g. foo.i -> foo.c)
so we can correctly initialize debug output. */
- no_backend = (*lang_hooks.post_options) (&main_input_filename);
+ no_backend = lang_hooks.post_options (&main_input_filename);
+#ifndef USE_MAPPED_LOCATION
input_filename = main_input_filename;
+#endif
#ifdef OVERRIDE_OPTIONS
/* Some machines may reject certain combinations of options. */
OVERRIDE_OPTIONS;
#endif
+ if (flag_section_anchors && !target_supports_section_anchors_p ())
+ {
+ warning (OPT_fsection_anchors,
+ "this target does not support %qs", "-fsection-anchors");
+ flag_section_anchors = 0;
+ }
+
+ if (flag_short_enums == 2)
+ flag_short_enums = targetm.default_short_enums ();
+
/* Set aux_base_name if not already set. */
if (aux_base_name)
;
@@ -4328,26 +1618,15 @@ process_options (void)
if (flag_unroll_all_loops)
flag_unroll_loops = 1;
- if (flag_unroll_loops)
- {
- flag_old_unroll_loops = 0;
- flag_old_unroll_all_loops = 0;
- }
-
- if (flag_old_unroll_all_loops)
- flag_old_unroll_loops = 1;
+ /* The loop unrolling code assumes that cse will be run after loop.
+ web and rename-registers also help when run after loop unrolling. */
- /* Old loop unrolling requires that strength_reduction be on also. Silently
- turn on strength reduction here if it isn't already on. Also, the loop
- unrolling code assumes that cse will be run after loop, so that must
- be turned on also. */
- if (flag_old_unroll_loops)
- {
- flag_strength_reduce = 1;
- flag_rerun_cse_after_loop = 1;
- }
- if (flag_unroll_loops || flag_peel_loops)
- flag_rerun_cse_after_loop = 1;
+ if (flag_rerun_cse_after_loop == AUTODETECT_VALUE)
+ flag_rerun_cse_after_loop = flag_unroll_loops || flag_peel_loops;
+ if (flag_web == AUTODETECT_VALUE)
+ flag_web = flag_unroll_loops || flag_peel_loops;
+ if (flag_rename_registers == AUTODETECT_VALUE)
+ flag_rename_registers = flag_unroll_loops || flag_peel_loops;
if (flag_non_call_exceptions)
flag_asynchronous_unwind_tables = 1;
@@ -4359,17 +1638,20 @@ process_options (void)
if (flag_unit_at_a_time && ! lang_hooks.callgraph.expand_function)
flag_unit_at_a_time = 0;
+ if (!flag_unit_at_a_time)
+ flag_section_anchors = 0;
+
if (flag_value_profile_transformations)
flag_profile_values = 1;
/* Warn about options that are not supported on this machine. */
#ifndef INSN_SCHEDULING
if (flag_schedule_insns || flag_schedule_insns_after_reload)
- warning ("instruction scheduling not supported on this target machine");
+ warning (0, "instruction scheduling not supported on this target machine");
#endif
#ifndef DELAY_SLOTS
if (flag_delayed_branch)
- warning ("this target machine does not have delayed branches");
+ warning (0, "this target machine does not have delayed branches");
#endif
user_label_prefix = USER_LABEL_PREFIX;
@@ -4383,7 +1665,7 @@ process_options (void)
user_label_prefix = flag_leading_underscore ? "_" : "";
}
else
- warning ("-f%sleading-underscore not supported on this target machine",
+ warning (0, "-f%sleading-underscore not supported on this target machine",
flag_leading_underscore ? "" : "no-");
}
@@ -4409,6 +1691,30 @@ process_options (void)
/* Now we know write_symbols, set up the debug hooks based on it.
By default we do nothing for debug output. */
+ if (PREFERRED_DEBUGGING_TYPE == NO_DEBUG)
+ default_debug_hooks = &do_nothing_debug_hooks;
+#if defined(DBX_DEBUGGING_INFO)
+ else if (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG)
+ default_debug_hooks = &dbx_debug_hooks;
+#endif
+#if defined(XCOFF_DEBUGGING_INFO)
+ else if (PREFERRED_DEBUGGING_TYPE == XCOFF_DEBUG)
+ default_debug_hooks = &xcoff_debug_hooks;
+#endif
+#ifdef SDB_DEBUGGING_INFO
+ else if (PREFERRED_DEBUGGING_TYPE == SDB_DEBUG)
+ default_debug_hooks = &sdb_debug_hooks;
+#endif
+#ifdef DWARF2_DEBUGGING_INFO
+ else if (PREFERRED_DEBUGGING_TYPE == DWARF2_DEBUG)
+ default_debug_hooks = &dwarf2_debug_hooks;
+#endif
+#ifdef VMS_DEBUGGING_INFO
+ else if (PREFERRED_DEBUGGING_TYPE == VMS_DEBUG
+ || PREFERRED_DEBUGGING_TYPE == VMS_AND_DWARF2_DEBUG)
+ default_debug_hooks = &vmsdbg_debug_hooks;
+#endif
+
if (write_symbols == NO_DEBUG)
;
#if defined(DBX_DEBUGGING_INFO)
@@ -4435,6 +1741,31 @@ process_options (void)
error ("target system does not support the \"%s\" debug format",
debug_type_names[write_symbols]);
+ /* Now we know which debug output will be used so we can set
+ flag_var_tracking, flag_rename_registers if the user has
+ not specified them. */
+ if (debug_info_level < DINFO_LEVEL_NORMAL
+ || debug_hooks->var_location == do_nothing_debug_hooks.var_location)
+ {
+ if (flag_var_tracking == 1)
+ {
+ if (debug_info_level < DINFO_LEVEL_NORMAL)
+ warning (0, "variable tracking requested, but useless unless "
+ "producing debug info");
+ else
+ warning (0, "variable tracking requested, but not supported "
+ "by this debug format");
+ }
+ flag_var_tracking = 0;
+ }
+
+ if (flag_rename_registers == AUTODETECT_VALUE)
+ flag_rename_registers = default_debug_hooks->var_location
+ != do_nothing_debug_hooks.var_location;
+
+ if (flag_var_tracking == AUTODETECT_VALUE)
+ flag_var_tracking = optimize >= 1;
+
/* If auxiliary info generation is desired, open the output file.
This goes in the same directory as the source file--unlike
all the other output files. */
@@ -4442,39 +1773,39 @@ process_options (void)
{
aux_info_file = fopen (aux_info_file_name, "w");
if (aux_info_file == 0)
- fatal_error ("can't open %s: %m", aux_info_file_name);
+ fatal_error ("can%'t open %s: %m", aux_info_file_name);
}
if (! targetm.have_named_sections)
{
if (flag_function_sections)
{
- warning ("-ffunction-sections not supported for this target");
+ warning (0, "-ffunction-sections not supported for this target");
flag_function_sections = 0;
}
if (flag_data_sections)
{
- warning ("-fdata-sections not supported for this target");
+ warning (0, "-fdata-sections not supported for this target");
flag_data_sections = 0;
}
}
if (flag_function_sections && profile_flag)
{
- warning ("-ffunction-sections disabled; it makes profiling impossible");
+ warning (0, "-ffunction-sections disabled; it makes profiling impossible");
flag_function_sections = 0;
}
#ifndef HAVE_prefetch
if (flag_prefetch_loop_arrays)
{
- warning ("-fprefetch-loop-arrays not supported for this target");
+ warning (0, "-fprefetch-loop-arrays not supported for this target");
flag_prefetch_loop_arrays = 0;
}
#else
if (flag_prefetch_loop_arrays && !HAVE_prefetch)
{
- warning ("-fprefetch-loop-arrays not supported for this target (try -march switches)");
+ warning (0, "-fprefetch-loop-arrays not supported for this target (try -march switches)");
flag_prefetch_loop_arrays = 0;
}
#endif
@@ -4483,18 +1814,46 @@ process_options (void)
make much sense anyway, so don't allow it. */
if (flag_prefetch_loop_arrays && optimize_size)
{
- warning ("-fprefetch-loop-arrays is not supported with -Os");
+ warning (0, "-fprefetch-loop-arrays is not supported with -Os");
flag_prefetch_loop_arrays = 0;
}
#ifndef OBJECT_FORMAT_ELF
+#ifndef OBJECT_FORMAT_MACHO
if (flag_function_sections && write_symbols != NO_DEBUG)
- warning ("-ffunction-sections may affect debugging on some targets");
+ warning (0, "-ffunction-sections may affect debugging on some targets");
+#endif
#endif
- /* The presence of IEEE signaling NaNs, implies all math can trap. */
- if (flag_signaling_nans)
- flag_trapping_math = 1;
+ /* The presence of IEEE signaling NaNs, implies all math can trap. */
+ if (flag_signaling_nans)
+ flag_trapping_math = 1;
+
+ /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */
+ if (flag_cx_limited_range)
+ flag_complex_method = 0;
+
+ /* Targets must be able to place spill slots at lower addresses. If the
+ target already uses a soft frame pointer, the transition is trivial. */
+ if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
+ {
+ warning (0, "-fstack-protector not supported for this target");
+ flag_stack_protect = 0;
+ }
+ if (!flag_stack_protect)
+ warn_stack_protect = 0;
+
+ /* ??? Unwind info is not correct around the CFG unless either a frame
+ pointer is present or A_O_A is set. Fixing this requires rewriting
+ unwind info generation to be aware of the CFG and propagating states
+ around edges. */
+ if (flag_unwind_tables && !ACCUMULATE_OUTGOING_ARGS
+ && flag_omit_frame_pointer)
+ {
+ warning (0, "unwind tables currently requires a frame pointer "
+ "for correctness");
+ flag_omit_frame_pointer = 0;
+ }
}
/* Initialize the compiler back end. */
@@ -4507,15 +1866,13 @@ backend_init (void)
/* Enable line number info for traceback. */
|| debug_info_level > DINFO_LEVEL_NONE
#endif
- || flag_test_coverage
- || warn_notreached);
+ || flag_test_coverage);
+ init_rtlanal ();
init_regs ();
init_fake_stack_mems ();
init_alias_once ();
- init_loop ();
init_reload ();
- init_function_once ();
init_varasm_once ();
/* The following initialization functions need to generate rtl, so
@@ -4531,12 +1888,20 @@ backend_init (void)
static int
lang_dependent_init (const char *name)
{
+ location_t save_loc = input_location;
if (dump_base_name == 0)
- dump_base_name = name ? name : "gccdump";
+ dump_base_name = name && name[0] ? name : "gccdump";
/* Other front-end initialization. */
- if ((*lang_hooks.init) () == 0)
+#ifdef USE_MAPPED_LOCATION
+ input_location = BUILTINS_LOCATION;
+#else
+ input_filename = "<built-in>";
+ input_line = 0;
+#endif
+ if (lang_hooks.init () == 0)
return 0;
+ input_location = save_loc;
init_asm_output (name);
@@ -4555,7 +1920,7 @@ lang_dependent_init (const char *name)
predefined types. */
timevar_push (TV_SYMOUT);
-#ifdef DWARF2_UNWIND_INFO
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
if (dwarf2out_do_frame ())
dwarf2out_frame_init ();
#endif
@@ -4594,23 +1959,7 @@ finalize (void)
fatal_error ("error closing %s: %m", asm_file_name);
}
- /* Do whatever is necessary to finish printing the graphs. */
- if (graph_dump_format != no_graph)
- {
- int i;
-
- for (i = 0; i < (int) DFI_MAX; ++i)
- if (dump_file[i].initialized && dump_file[i].graph_dump_p)
- {
- char seq[16];
- char *suffix;
-
- sprintf (seq, DUMPFILE_FORMAT, i);
- suffix = concat (seq, dump_file[i].extension, NULL);
- finish_graph_dump_file (dump_base_name, suffix);
- free (suffix);
- }
- }
+ finish_optimization_passes ();
if (mem_report)
{
@@ -4620,13 +1969,14 @@ finalize (void)
dump_rtx_statistics ();
dump_varray_statistics ();
dump_alloc_pool_statistics ();
+ dump_ggc_loc_statistics ();
}
/* Free up memory for the benefit of leak detectors. */
free_reg_info ();
/* Language-specific end of compilation actions. */
- (*lang_hooks.finish) ();
+ lang_hooks.finish ();
}
/* Initialize the compiler, and compile the input file. */
@@ -4655,23 +2005,7 @@ do_compile (void)
/* Language-dependent initialization. Returns true on success. */
if (lang_dependent_init (main_input_filename))
- {
- if (flag_unit_at_a_time)
- {
- open_dump_file (DFI_cgraph, NULL);
- cgraph_dump_file = rtl_dump_file;
- rtl_dump_file = NULL;
- }
-
- compile_file ();
-
- if (flag_unit_at_a_time)
- {
- rtl_dump_file = cgraph_dump_file;
- cgraph_dump_file = NULL;
- close_dump_file (DFI_cgraph, NULL, NULL_RTX);
- }
- }
+ compile_file ();
finalize ();
}
OpenPOWER on IntegriCloud